package com.sz.biz.logistics.ord.service.impl;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.sz.biz.common.base.dto.AreaDto;
import com.sz.biz.common.base.dto.CountryModel;
import com.sz.biz.common.base.service.AreaManager;
import com.sz.biz.common.base.service.AreaService;
import com.sz.biz.common.constants.CommCodes;
import com.sz.biz.common.constants.LanguageCode;
import com.sz.biz.common.constants.ModuleNames;
import com.sz.biz.common.customer.entity.CusCustomer;
import com.sz.biz.common.customer.entity.CusUser;
import com.sz.biz.common.customer.service.CustomerService;
import com.sz.biz.common.customer.service.CustomerUserService;
import com.sz.biz.common.utils.OrderMake;
import com.sz.biz.logistics.base.entity.Airport;
import com.sz.biz.logistics.base.entity.Port;
import com.sz.biz.logistics.base.service.AirportService;
import com.sz.biz.logistics.base.service.PortService;
import com.sz.biz.logistics.billing.service.QuotationCalcService;
import com.sz.biz.logistics.constants.ErrorCodes;
import com.sz.biz.logistics.constants.RegionConstants;
import com.sz.biz.logistics.core.dto.*;
import com.sz.biz.logistics.core.entity.Product;
import com.sz.biz.logistics.core.entity.ProductServiceRel;
import com.sz.biz.logistics.core.service.ProductCargoTypeRelService;
import com.sz.biz.logistics.core.service.ProductService;
import com.sz.biz.logistics.ord.constants.OrderConstants;
import com.sz.biz.logistics.ord.dto.*;
import com.sz.biz.logistics.ord.entity.*;
import com.sz.biz.logistics.ord.enums.OrdOperationLogEnum;
import com.sz.biz.logistics.ord.enums.OrderStatusToServiceTypeEnum;
import com.sz.biz.logistics.ord.enums.TransportTypeEnum;
import com.sz.biz.logistics.ord.service.*;
import com.sz.biz.logistics.serialno.entity.SerialNoManagement;
import com.sz.biz.logistics.serialno.service.NoManagementService;
import com.sz.biz.pay.constants.PayStatus;
import com.sz.common.base.constants.UserActions;
import com.sz.common.base.dao.ParamData;
import com.sz.common.base.dto.QResultDto;
import com.sz.common.base.dto.QueryParams;
import com.sz.common.base.dto.ResultDto;
import com.sz.common.base.exception.CommonErrorCodes;
import com.sz.common.base.exception.Exceptions;
import com.sz.common.base.service.AbstractService;
import com.sz.common.base.utils.*;
import com.sz.common.core.constants.SysErrorCodes;
import com.sz.common.core.service.PrincipalLogUtils;
import com.sz.common.core.service.PrincipalUtils;
import com.sz.common.core.system.dto.UserDto;
import com.sz.common.core.system.entity.SysDict;
import com.sz.common.core.system.entity.SysFile;
import com.sz.common.core.system.service.SysDictService;
import com.sz.common.core.system.service.SysFileService;
import com.sz.common.core.system.service.UserService;
import org.apache.commons.collections.map.HashedMap;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.*;
import java.util.concurrent.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Package: com.sz.biz.logistics.ord.service.impl<br>
 * Function: TODO: ADD FUNCTION <br>
 * Author: yanhong.xiao.<br>
 * Date: 2017-11-22 18:37:00.
 */
@Service
public class OrdOrderBatchServiceImpl extends AbstractService implements OrdOrderBatchService {

    private static final int MIN_DATA_LEN = 12;
    private static final String FROM_ADDRESS = "fromAddress";
    private static final String TO_ADDRESS = "toAddress";
    private static final String FETCH_ADDRESS = "fetchAddress";

    @Override
    protected String getMapperNamespace() {
        return "com.sz.biz.logistics.ord.OrdOrderBatchMapper";
    }

    @Autowired
    private OrdOrderServiceAssignService ordOrderServiceAssignService;
    @Autowired
    private QuotationCalcService quotationCalcService;
    @Autowired
    private OrdOrderFeeService orderFeeService;

    @Autowired
    private CustomerUserService customerUserService;

    @Autowired
    private CustomerService customerService;

    @Autowired
    private ProductService productService;

    @Autowired
    private ProductCargoTypeRelService productCargoTypeRelService;

    @Autowired
    private SysDictService sysDictService;
    @Autowired
    private PortService portService;
    @Autowired
    private AirportService airportService;
    @Autowired
    private AreaService areaService;

    @Autowired
    private OrdOrderService ordOrderService;
    @Autowired
    private OrdSubOrderService subOrderService;
    @Autowired
    private OrdOrderAddressService orderAddressService;

    @Autowired
    private OrdOrderAdditionalService orderAdditionalService;

    @Autowired
    private AreaManager areaManager;
    @Autowired
    private OrdOrderCargoService orderCargoService;

    @Autowired
    private OrdOrderTrackingService orderTrackingService;

    @Autowired
    private BizOperationLogService bizOperationLogService;

    @Autowired
    private OrdOrderFileService orderFileService;

    @Autowired
    private UserService userService;


    @Autowired
    private SysFileService sysFileService;
    @Autowired
    private OrdTrackingMessageService trackingMessageService;
    @Autowired
    private NoManagementService noManagementService;

    /**
     * 创建一个线程池
     */
    private ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("osaprefee-calc-pool-%d").build();
    /**
     * Common Thread Pool
     */
    private ExecutorService pool = new ThreadPoolExecutor(5, 200,
            0L, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());


    @Override
    public List<String> queryBatchNumbers(int accountId, int type) {
        Map<String, Object> map = Maps.newHashMap();
        map.put("type", type);
        map.put("createUserId", accountId);
        List<String> batchNumbers = dao.findForList(getSqlName("queryBatchNumbersByAccountId"), map, String.class);
        return batchNumbers;
    }

    @Override
    public void deleteByBatchNumber(String batchNumber) {
        dao.delete(getSqlName("deleteByBatchNumber"), batchNumber);
    }


    @Override
    public void deleteByBatchNumbers(List<String> batchNumbers) {
        Map<String, Object> params = Maps.newHashMap();
        params.put("batchNumbers", batchNumbers);
        dao.delete(getSqlName("deleteByBatchNumbers"), params);
    }

    @Override
    public void saveOrderBatches(List<OrdOrderBatch> orderBatchList) {
        dao.batchInsert(getSqlName("insert"), orderBatchList);
    }

    @Override
    public void saveOrderBatch(OrdOrderBatch ordOrderBatch) {
        dao.save(getSqlName("insert"), ordOrderBatch);
    }


    /**
     * 批量订单数据的查询
     *
     * @param params
     */
    @Override
    public QResultDto findSearchDtoByParam(QueryParams params) {
        ParamData pd = convertQueryParams(params);
        //1、根据条件查询相应的运单编号
        List<OrdOrderBatch> ordOrderBatchList = dao.findForList(getSqlName("searchOrderBatchListPage"), pd, OrdOrderBatch.class);
        List<OrdOrderBatchDto> orderBatchDtoList = Lists.newArrayList();
        if (!CollectionUtils.isEmpty(ordOrderBatchList)) {
            ordOrderBatchList.forEach(ordOrderBatch -> {
                OrdOrderBatchDto dto = new OrdOrderBatchDto();
                dto.setId(ordOrderBatch.getId());
                dto.setExternalNo(ordOrderBatch.getExternalNo());
                dto.setProductName(ordOrderBatch.getProductNameOrCode());
                dto.setCargoTypeName(ordOrderBatch.getCargoType());
                dto.setFromAddress(getAdderssFromBatch(ordOrderBatch, CommCodes.ADDRESS_TYPE_FROM));
                dto.setToAddress(getAdderssFromBatch(ordOrderBatch, CommCodes.ADDRESS_TYPE_TO));
                dto.setVerifiedStatus(ordOrderBatch.getVerifiedStatus());
                orderBatchDtoList.add(dto);
            });
        }
        return new QResultDto(orderBatchDtoList, pd.getPagination());

    }


    /**
     * 根据orderBatch的id获取orderDto
     *
     * @param id
     * @return
     */
    @Override
    public OrdOrderBatchDetailResultDto getDtoById(Integer id) {
        OrdOrderBatchDetailResultDto detailResultDto = new OrdOrderBatchDetailResultDto();
        OrdOrderBatch orderBatch = getById(id);
        if (null == orderBatch) {
            throw Exceptions.bizException(ErrorCodes.ERROR_ORD_BATCH_ORDER_NOT_EXISTS);
        }
        OrdOrderBatchDetailDto detailDto = new OrdOrderBatchDetailDto();
        EntityUtils.copyPropertiesIgnoreNull(orderBatch, detailDto);
        detailDto.setProductName(orderBatch.getProductNameOrCode());
        detailDto.setCargoTypeName(orderBatch.getCargoType());
        Map<String, String> sysDictUnitWeightMap = sysDictService.findMapByCatalog(CommCodes.SYS_DICT_BIZ_UNIT_WEIGHT);
        detailDto.setCusWeightUnitName(sysDictUnitWeightMap.get(detailDto.getCusWeightUnit()));
        /**
         * 附件地址
         */
        if (org.apache.commons.lang3.StringUtils.isNotBlank(orderBatch.getAttaches())) {
            OrdOrderBatchFileList batchFileList = JsonUtils.toObject(orderBatch.getAttaches(), OrdOrderBatchFileList.class);
            detailDto.setFileDtos(batchFileList.getAttaches());
        }
        detailResultDto.setOrderBatchDetailDto(detailDto);
        //  重新校验之后给出数据
        orderBatch.setVerifiedStatus(false);
        String oldAdditionalTypeCode = null == orderBatch.getAdditionalTypeCode() ? "" : orderBatch.getAdditionalTypeCode();

        if (orderBatch.getVerifiedStatus() == false) {
            List<Map<String, OrdOrderBatchErrorDto>> errorMapList = getBatchOrderFailDetail(Arrays.asList(orderBatch));
            String newAdditionalTypeCode = null == orderBatch.getAdditionalTypeCode() ? "" : orderBatch.getAdditionalTypeCode();
            if (!oldAdditionalTypeCode.equals(newAdditionalTypeCode)) {
                //更新附加服务的code
                updateAdditionalTypeCode(orderBatch);
            }
            if (!CollectionUtils.isEmpty(errorMapList)) {
                detailResultDto.setErrorDtoMap(errorMapList.get(0));
            }
        }
        /**
         * 处理产品  productId , productUid,货物类型， productCode
         *
         */
        String productData = orderBatch.getRedundanceData();
        Map<String, String> dataMap = this.getStringStringMap(productData);
        //产品名称没有错误  productId:12|productUid:23437478374234|cargoType:GT001
        String productId = dataMap.get("productId");
        if (org.apache.commons.lang3.StringUtils.isNotBlank(productId)) {
            detailDto.setProductId(Integer.parseInt(productId));
        }
        detailDto.setProductUid(dataMap.get("productUid"));
        detailDto.setCargoType(dataMap.get("cargoType"));
        detailDto.setProductCode(dataMap.get("productCode"));

        /**
         * 处理附加服务。additionalTypeCode  是竖线隔开的
         */
        String additionalTypeCode = orderBatch.getAdditionalTypeCode();
        if (org.apache.commons.lang3.StringUtils.isNotBlank(additionalTypeCode)) {
            String[] additionalTypeCodes = additionalTypeCode.split("\\|");
            //orderAdditionalDtos
            if (null != additionalTypeCodes && additionalTypeCodes.length > 0) {
                List<OrdOrderAdditionalDto> orderAdditionalDtos = Lists.newArrayList();
                Map<String, String> serviceTypeCodeMap = sysDictService.findMapByCatalog(CommCodes.SYS_DICT_BIZ_SERVICE_TYPE);
                for (String code : additionalTypeCodes) {
                    OrdOrderAdditionalDto additionalDto = new OrdOrderAdditionalDto();
                    additionalDto.setServiceTypeCode(code);
                    String serviceTypeCodeName = serviceTypeCodeMap.get(code);
                    if (org.apache.commons.lang3.StringUtils.isNotBlank(serviceTypeCodeName)) {
                        additionalDto.setServiceTypeName(serviceTypeCodeName);
                    }
                    orderAdditionalDtos.add(additionalDto);
                }
                detailDto.setOrderAdditionalDtos(orderAdditionalDtos);
            }
        }

        /**
         * 物品明细
         */
        OrdOrderBatchCargoList cargoList = JsonUtils.toObject(orderBatch.getGoodsDetail(), OrdOrderBatchCargoList.class);
        if (null != cargoList && !CollectionUtils.isEmpty(cargoList.getCargos())) {
            detailDto.setCargos(cargoList.getCargos());
        }
        //处理地址的id

        /**
         * 发件人地址
         */
        detailDto.setFromName(orderBatch.getFromName());
        detailDto.setFromTelephone(orderBatch.getFromTelephone());
        detailDto.setFromPhone(orderBatch.getFromPhone());
        detailDto.setFromAddress(getAdderssFromBatch(orderBatch, CommCodes.ADDRESS_TYPE_FROM));

        /**
         * 收件人地址
         */
        detailDto.setToName(orderBatch.getToName());
        detailDto.setToTelephone(orderBatch.getToTelephone());
        detailDto.setToPhone(orderBatch.getToPhone());
        detailDto.setToAddress(getAdderssFromBatch(orderBatch, CommCodes.ADDRESS_TYPE_TO));
        /**
         * 根据产品处理地址类型
         */
        String transportType = dataMap.get("transportType");
        if (StringUtils.isNumber(transportType)) {
            detailDto.getFromAddress().setTransportType(Integer.parseInt(transportType));
            detailDto.getToAddress().setTransportType(Integer.parseInt(transportType));
        }
        /**
         * 处理揽货地址
         */
        if (org.apache.commons.lang3.StringUtils.isNotBlank(orderBatch.getFetchCountry())) {
            detailDto.setFetchName(orderBatch.getFetchName());
            detailDto.setFetchTelephone(orderBatch.getFetchTelephone());
            detailDto.setFetchPhone(orderBatch.getFetchPhone());
            detailDto.setFetchAddress(getAdderssFromBatch(orderBatch, CommCodes.ADDRESS_TYPE_FETCH));
            //提货地址为速运地址
            detailDto.getFetchAddress().setTransportType(CommCodes.TRANSPORT_LAND);

        }
        return detailResultDto;
    }

    @Override
    public List<OrdOrderBatch> findByBatchNumber(String batchNumber) {
        List<OrdOrderBatch> ordOrderBatchList = new ArrayList<>();
        if (!StringUtils.isEmpty(batchNumber)) {
            ParamData pd = new ParamData();
            pd.put("batchNumber", batchNumber);
            ordOrderBatchList = dao.findForList(getSqlName("findByBatchNumber"), pd, OrdOrderBatch.class);
        }

        return ordOrderBatchList;
    }

    public int findVerifiedFail(String batchNumber) {
        int count = 0;
        if (!StringUtils.isEmpty(batchNumber)) {
            ParamData pd = new ParamData();
            pd.put("batchNumber", batchNumber);
            count = (int) dao.findForObject(getSqlName("findVerifiedFail"), pd);
        }
        return count;
    }

    /**
     * 修改批量订单数据
     *
     * @param detailDto
     */
    @Override
    @Transactional
    public void updateByDto(OrdOrderBatchDetailDto detailDto) {
        /**
         * 1. 查看批量订单数据是否存在
         */
        OrdOrderBatch oldOrderBatch = getById(detailDto.getId());
        if (null == oldOrderBatch) {
            throw Exceptions.bizException(ErrorCodes.ERROR_ORD_BATCH_ORDER_NOT_EXISTS);
        }

        OrdOrderBatch orderBatch = new OrdOrderBatch();
        EntityUtils.copyPropertiesIgnoreNull(detailDto, orderBatch);

        //转productNameOrCode
        //  orderBatch.setProductNameOrCode(detailDto.getProductName());
        orderBatch.setProductNameOrCode(detailDto.getProductCode());
        //转货物类型
        orderBatch.setCargoType(detailDto.getCargoTypeName());
        orderBatch.setBatchNumber(oldOrderBatch.getBatchNumber());
        orderBatch.setCustomerId(oldOrderBatch.getCustomerId());
        orderBatch.setCusUserId(oldOrderBatch.getCusUserId());
        orderBatch.setCreateUserId(oldOrderBatch.getCreateUserId());
        orderBatch.setCreateTime(oldOrderBatch.getCreateTime());
        //处理地址
        /**
         * 处理发件人地址
         */
        OrderAddressModel fromAddress = detailDto.getFromAddress();
        orderBatch.setFromCountry(fromAddress.getCountryCode());
        String fromTransportName = fromAddress.getTransportName();
        if (fromAddress.getTransportType() == CommCodes.TRANSPORT_SEA) {
            // orderBatch.setFromDistrict(fromAddress.getTransportName());
            if (!StringUtils.isEmpty(fromTransportName)) {
                orderBatch.setFromDistrict(fromTransportName.substring(0, fromTransportName.indexOf("(")));
            }
        } else if (fromAddress.getTransportType() == CommCodes.TRANSPORT_AIR) {
            if (!StringUtils.isEmpty(fromTransportName)) {
                orderBatch.setFromDistrict(fromTransportName.substring(fromTransportName.indexOf("(") + 1, fromTransportName.length() - 1));
            }
            //  orderBatch.setFromDistrict(fromAddress.getTransportCode());
        } else {
            //陆运
            orderBatch.setFromProvince(fromAddress.getProvinceName());
            orderBatch.setFromCity(fromAddress.getCityName());
            orderBatch.setFromDistrict(fromAddress.getDistrictName());
        }
        orderBatch.setFromAddress(fromAddress.getAddress());
        orderBatch.setFromStreet(fromAddress.getStreetName());
        orderBatch.setFromPostcode(fromAddress.getPostcode());
        orderBatch.setFromEmail(fromAddress.getEmail());

        /**
         * 处理收件人地址
         */
        OrderAddressModel toAddress = detailDto.getToAddress();
        orderBatch.setToCountry(toAddress.getCountryCode());

        orderBatch.setToAddress(toAddress.getAddress());
        String transportName = toAddress.getTransportName();
        if (toAddress.getTransportType() == CommCodes.TRANSPORT_SEA) {
            if (!StringUtils.isEmpty(transportName)) {
                orderBatch.setToDistrict(transportName.substring(0, transportName.indexOf("(")));
            }
        } else if (toAddress.getTransportType() == CommCodes.TRANSPORT_AIR) {
            if (!StringUtils.isEmpty(transportName)) {
                orderBatch.setToDistrict(transportName.substring(transportName.indexOf("(") + 1, transportName.length() - 1));
            }
        } else {
            orderBatch.setToProvince(toAddress.getProvinceName());
            orderBatch.setToCity(toAddress.getCityName());
            orderBatch.setToDistrict(toAddress.getDistrictName());
        }
        orderBatch.setToStreet(toAddress.getStreetName());
        orderBatch.setToPostcode(toAddress.getPostcode());
        orderBatch.setToEmail(toAddress.getEmail());

        /**
         * 处理提货地址
         */
        OrderAddressModel fetchAddress = detailDto.getFetchAddress();
        orderBatch.setFetchCountry(fetchAddress.getCountryCode());
        orderBatch.setFetchProvince(fetchAddress.getProvinceName());
        orderBatch.setFetchCity(fetchAddress.getCityName());
        orderBatch.setFetchDistrict(fetchAddress.getDistrictName());
        orderBatch.setFetchStreet(fetchAddress.getStreetName());
        orderBatch.setFetchPostcode(fetchAddress.getPostcode());
        orderBatch.setFetchEmail(fetchAddress.getEmail());
        orderBatch.setFetchAddress(fetchAddress.getAddress());


        //转换 附加服务，物品明细,附件,
        List<OrdOrderAdditionalDto> orderAdditionalDtos = detailDto.getOrderAdditionalDtos();
        if (!CollectionUtils.isEmpty(orderAdditionalDtos)) {
            StringBuilder additionalTypeCode = new StringBuilder();
            orderAdditionalDtos.forEach(ordOrderAdditionalDto -> {
                additionalTypeCode.append(ordOrderAdditionalDto.getServiceTypeCode() + "|");
            });
            String typeCodeStr = additionalTypeCode.toString();
            typeCodeStr = typeCodeStr.substring(0, additionalTypeCode.length() - 1);
            orderBatch.setAdditionalTypeCode(typeCodeStr);
        }

        //转换附加服务的标志
        if (org.apache.commons.lang3.StringUtils.isNotBlank(orderBatch.getAdditionalTypeCode()) && orderBatch.getAdditionalTypeCode().contains(OrderStatusToServiceTypeEnum.RECEGOOD.getName())) {
            orderBatch.setFetchFlag(true);
        } else {
            orderBatch.setFetchFlag(false);
        }

        //转换货物明细
        List<OrdOrderBatchCargo> cargos = detailDto.getCargos();
        if (!CollectionUtils.isEmpty(cargos)) {
            OrdOrderBatchCargoList cargoList = new OrdOrderBatchCargoList();
            cargoList.setCargos(cargos);
            orderBatch.setGoodsDetail(JsonUtils.toJSONString(cargoList));
        }

        orderBatch.setVerifiedStatus(false);
        // 转换附件明细
        List<OrdOrderFileDto> fileDtos = detailDto.getFileDtos();
        if (!CollectionUtils.isEmpty(fileDtos)) {
            fileDtos.forEach(fileDto -> {
                String fileId = fileDto.getFileId();
                SysFile sysFile = sysFileService.getFileInfo(fileId);
                if (null != sysFile) {
                    fileDto.setFileUrl(sysFile.getFileLocation());
                    fileDto.setFileType(sysFile.getContentType());
                    fileDto.setFileRandomName(sysFile.getFileName());
                } else {
                    throw Exceptions.bizException(ErrorCodes.ERROR_COMMON, "附件名称为" + fileDto.getFileName() + "的附件不存在");
                }
                fileDto.setOrderStatus(OrderStatus.DRAFT);
                fileDto.setCreateUserType(CommCodes.CUSTOMER_USER_TYPE);
                fileDto.setCreateTime(new Date());
                fileDto.setCreateUserId(PrincipalUtils.getAccountId());
                fileDto.setLastUpdateUserId(fileDto.getCreateUserId());

            });
            OrdOrderBatchFileList fileList = new OrdOrderBatchFileList();
            fileList.setAttaches(fileDtos);
            orderBatch.setAttaches(JsonUtils.toJSONString(fileList));
        }

        //校验信息
        Map<String, OrdOrderBatchErrorDto> errorDtoMap = getBatchOrderFailInfoForSave(Arrays.asList(orderBatch));
        if (!CollectionUtils.isEmpty(errorDtoMap)) {
            //校验有错误。
            errorDtoMap.forEach((k, v) -> {
                throw Exceptions.bizException(ErrorCodes.ERROR_COMMON, v.getMessage());
            });
        }
        orderBatch.setVerifiedStatus(true);
        updateOrderBatch(orderBatch);

        //增加操作日志
        Map<String, Object> dataBackup = Maps.newHashMap();
        dataBackup.put("UPDATE_ORDER_BATCH_EXCEL", detailDto);
        PrincipalLogUtils.addOperationLog(ModuleNames.ORD, ModuleNames.ORD_ORDER_BATCH_EXCEL, UserActions.UPDATE, "修改excel批量订单", dataBackup);

    }


    @Override
    public OrdOrderBatch getById(Integer id) {
        return (OrdOrderBatch) dao.findForObject(getSqlName("selectByPrimaryKey"), id);

    }

    @Override
    public void updateOrderBatch(OrdOrderBatch ordOrderBatch) {
        if (!ObjectUtils.isEmpty(ordOrderBatch)) {
            dao.update(getSqlName("updateByPrimaryKey"), ordOrderBatch);
        }
    }

    @Override
    public void batchDeleteByIds(String batchNumber, List<Integer> ids) {
        Map<String, Object> paramMap = Maps.newHashMap();
        paramMap.put("batchNumber", batchNumber);
        if (!CollectionUtils.isEmpty(ids)) {
            paramMap.put("ids", ids);
        }
        if (!CollectionUtils.isEmpty(ids)) {
            dao.delete(getSqlName("batchDeleteByIds"), paramMap);
        }
        //增加系统操作日志
        Map<String, Object> dataBackup = new HashMap<>();
        dataBackup.put("DELETE_ORDER_BATCH_EXCEL", ids);
        PrincipalLogUtils.addOperationLog(ModuleNames.ORD, ModuleNames.ORD_ORDER, UserActions.DELETE, "删除批量订单数据", dataBackup);
    }

    @Override
    public void updateDetailCode(OrdOrderBatch ordOrderBatch) {
        if (StringUtils.isEmpty(ordOrderBatch.getFromDetailCode())
                && StringUtils.isEmpty(ordOrderBatch.getToDetailCode())
                && StringUtils.isEmpty(ordOrderBatch.getFetchDetailCode())) {
            return;
        }
        dao.update(getSqlName("updateDetailCode"), ordOrderBatch);
    }

    @Override
    public void updateCargos(OrdOrderBatch ordOrderBatch) {

        dao.update(getSqlName("updateGoodsDetail"), ordOrderBatch);

    }

    @Override
    public void updateVerifiedStatus(List<Integer> ids, Boolean status) {
        Map<String, Object> params = Maps.newHashMap();
        params.put("ids", ids);
        params.put("status", status);
        dao.update(getSqlName("updateVerifiedStatus"), params);
    }

    @Override
    public void updateAdditionalTypeCode(OrdOrderBatch ordOrderBatch) {
        dao.update(getSqlName("updateAdditionalTypeCode"), ordOrderBatch);
    }


    /**
     * 增加批量订单的附件
     *
     * @param orderBatchId
     * @param ordOrderFileDto
     */
    @Override
    public OrdOrderFileDto addOrderFile(Integer orderBatchId, OrdOrderFileDto ordOrderFileDto) {
        OrdOrderBatch oldOrderBatch = getById(orderBatchId);
        if (null == oldOrderBatch) {
            //批量订单数据不存在
            throw Exceptions.bizException(ErrorCodes.ERROR_ORD_BATCH_ORDER_NOT_EXISTS);
        }
        //处理file信息
        SysFile file = sysFileService.getFileInfo(ordOrderFileDto.getFileId());
        if (null == file) {
            throw Exceptions.bizException(ErrorCodes.ERROR_ORD_ORDER_FILE_NOT_EXIST);
        }
        //校验名称
        if (checkUniqueName(oldOrderBatch, ordOrderFileDto.getFileName())) {
            throw Exceptions.bizException(ErrorCodes.ERROR_ORD_ORDER_FILE_NAME_EXIST);
        }
        //校验附件的格式是否为草稿或者已经提交的
        //检测状态通过
        orderFileService.checkFileStatus(OrderStatus.DRAFT, Arrays.asList(ordOrderFileDto));
        List<OrdOrderFileDto> fileDtos = Lists.newArrayList();
        OrdOrderBatchFileList batchFileList = new OrdOrderBatchFileList();
        String attatches = oldOrderBatch.getAttaches();
        if (!StringUtils.isEmpty(attatches)) {
            batchFileList = JsonUtils.toObject(attatches, OrdOrderBatchFileList.class);
            if (null != batchFileList) {
                fileDtos = batchFileList.getAttaches();
            }
        }
        ordOrderFileDto.setCreateUserId(PrincipalUtils.getAccountId());
        ordOrderFileDto.setCreateTime(new Date());
        ordOrderFileDto.setLastUpdateUserId(ordOrderFileDto.getCreateUserId());
        ordOrderFileDto.setFileUrl(file.getFileLocation());
        ordOrderFileDto.setFileType(file.getContentType());
        ordOrderFileDto.setFileRandomName(file.getFileName());
        ordOrderFileDto.setOrderStatus(OrderStatus.DRAFT);
        if (null == fileDtos) {
            fileDtos = Lists.newArrayList();
        }
        fileDtos.add(ordOrderFileDto);
        batchFileList.setAttaches(fileDtos);
        oldOrderBatch.setAttaches(JsonUtils.toJSONString(batchFileList));
        updateAttaches(oldOrderBatch);
        //获取数据库的所有文件配置
        Map<String, String> dictMap = sysDictService.findMapByCatalog(CommCodes.ORD_ORDER_FILE_TYPE_CATALOG);
        //处理创建人，创建时间
        if (ordOrderFileDto.getCreateUserType().intValue() == CommCodes.OPERATOR_USER_TYPE.intValue()) {
            UserDto u = userService.getUserById(ordOrderFileDto.getCreateUserId());
            ordOrderFileDto.setCreateUserName(u.getUserName());
        } else if (ordOrderFileDto.getCreateUserType().intValue() == CommCodes.CUSTOMER_USER_TYPE.intValue()) {
            CusUser cu = customerUserService.findById(ordOrderFileDto.getCreateUserId());
            ordOrderFileDto.setCreateUserName(cu.getUserName());
        }

        ordOrderFileDto.setFileUrl(file.getFileLocation());
        ordOrderFileDto.setFileTypeName(null == dictMap.get(ordOrderFileDto.getCode()) ? null : dictMap.get(ordOrderFileDto.getCode()));
        return ordOrderFileDto;
    }

    /**
     * 检查一个批量订单下的附件名称唯一性
     *
     * @param orderBatchId
     * @param fileName
     * @return
     */
    @Override
    public Boolean checkUniqueName(Integer orderBatchId, String fileName) {
        OrdOrderBatch oldOrderBatch = getById(orderBatchId);
        if (null == oldOrderBatch) {
            //批量订单数据不存在
            throw Exceptions.bizException(ErrorCodes.ERROR_ORD_BATCH_ORDER_NOT_EXISTS);
        }
        return checkUniqueName(oldOrderBatch, fileName);
    }

    private Boolean checkUniqueName(OrdOrderBatch ordOrderBatch, String fileName) {
        List<OrdOrderFileDto> fileDtos = Lists.newArrayList();
        OrdOrderBatchFileList batchFileList = new OrdOrderBatchFileList();
        String attatches = ordOrderBatch.getAttaches();
        if (!StringUtils.isEmpty(attatches)) {
            batchFileList = JsonUtils.toObject(attatches, OrdOrderBatchFileList.class);
            if (null != batchFileList) {
                fileDtos = batchFileList.getAttaches();
            }
        }
        boolean existNameFlag = false;
        if (!CollectionUtils.isEmpty(fileDtos)) {
            for (OrdOrderFileDto fileDto :
                    fileDtos) {
                if (fileDto.getFileName().equals(fileName)) {
                    existNameFlag = true;
                    break;
                }

            }

        }
        return existNameFlag;
    }


    @Override
    public void updateAttaches(OrdOrderBatch ordOrderBatch) {
        dao.update(getSqlName("updateAttaches"), ordOrderBatch);

    }

    /**
     * 删除附件
     *
     * @param orderBatchId
     * @param fileName
     */
    @Override
    public void deleteAttatches(Integer orderBatchId, String fileName) {
        OrdOrderBatch oldOrderBatch = getById(orderBatchId);
        if (null == oldOrderBatch) {
            //批量订单数据不存在
            throw Exceptions.bizException(ErrorCodes.ERROR_ORD_BATCH_ORDER_NOT_EXISTS);
        }
        List<OrdOrderFileDto> fileDtos = Lists.newArrayList();
        OrdOrderBatchFileList batchFileList = new OrdOrderBatchFileList();
        String attatches = oldOrderBatch.getAttaches();
        if (!StringUtils.isEmpty(attatches)) {
            batchFileList = JsonUtils.toObject(attatches, OrdOrderBatchFileList.class);
            if (null != batchFileList) {
                fileDtos = batchFileList.getAttaches();
            }
        }

        List<OrdOrderFileDto> newFileDtos = Lists.newArrayList();
        if (!CollectionUtils.isEmpty(fileDtos)) {
            for (OrdOrderFileDto fileDto :
                    fileDtos) {
                if (!(fileDto.getFileName().equals(fileName))) {
                    newFileDtos.add(fileDto);
                }

            }
        }

        if (newFileDtos.size() != fileDtos.size()) {
            batchFileList.setAttaches(newFileDtos);
            oldOrderBatch.setAttaches(JsonUtils.toJSONString(batchFileList));
            updateAttaches(oldOrderBatch);
        }


    }

    /**
     * 获取附件列表
     *
     * @param orderBatchId
     * @return
     */
    @Override
    public List<OrdOrderFileDto> getDtos(Integer orderBatchId) {
        OrdOrderBatch oldOrderBatch = getById(orderBatchId);
        if (null == oldOrderBatch) {
            //批量订单数据不存在
            throw Exceptions.bizException(ErrorCodes.ERROR_ORD_BATCH_ORDER_NOT_EXISTS);
        }
        List<OrdOrderFileDto> fileDtos = Lists.newArrayList();
        OrdOrderBatchFileList batchFileList;
        String attatches = oldOrderBatch.getAttaches();
        if (!StringUtils.isEmpty(attatches)) {
            batchFileList = JsonUtils.toObject(attatches, OrdOrderBatchFileList.class);
            if (null != batchFileList) {
                fileDtos = batchFileList.getAttaches();
            }
        }


        //获取数据库的所有文件配置
        List<SysDict> dictList = sysDictService.queryOrderFileTypes(CommCodes.ORD_ORDER_FILE_TYPE_CATALOG, null);
        Map<String, SysDict> dictMap = new HashedMap();
        if (org.apache.commons.collections.CollectionUtils.isNotEmpty(dictList)) {
            dictList.forEach(sysDict -> {
                dictMap.put(sysDict.getCode(), sysDict);
            });
        }

        if (!CollectionUtils.isEmpty(fileDtos)) {
            fileDtos.forEach(fileDto -> {
                fileDto.setFileTypeName(null == dictMap.get(fileDto.getCode()) ? null : dictMap.get(fileDto.getCode()).getName());
            });
        }
        return fileDtos;
    }


    private OrderAddressModel getAdderssFromBatch(OrdOrderBatch ordOrderBatch, String type) {
        if (StringUtils.isEmpty(type)) {
            return null;
        }
        //处理名称
        OrderAddressModel addressModel = new OrderAddressModel();
        //处理地址
        String detailCode;
        String detail;
        if (type.equals(CommCodes.ADDRESS_TYPE_FROM)) {
            detailCode = ordOrderBatch.getFromDetailCode();
            detail = ordOrderBatch.getFromDetail();
            addressModel.setCountryName(ordOrderBatch.getFromCountry());
            addressModel.setProvinceName(ordOrderBatch.getFromProvince());
            addressModel.setCountryName(ordOrderBatch.getFromCountry());
            addressModel.setCityName(ordOrderBatch.getFromCity());
            addressModel.setDistrictName(ordOrderBatch.getFromDistrict());
            addressModel.setStreetName(ordOrderBatch.getFromStreet());
            addressModel.setAddress(ordOrderBatch.getFromAddress());
            addressModel.setPostcode(ordOrderBatch.getFromPostcode());
            addressModel.setEmail(ordOrderBatch.getFromEmail());
        } else if (type.equals(CommCodes.ADDRESS_TYPE_TO)) {
            detailCode = ordOrderBatch.getToDetailCode();
            detail = ordOrderBatch.getToDetail();
            addressModel.setCountryName(ordOrderBatch.getToCountry());
            addressModel.setProvinceName(ordOrderBatch.getToProvince());
            addressModel.setCountryName(ordOrderBatch.getToCountry());
            addressModel.setCityName(ordOrderBatch.getToCity());
            addressModel.setDistrictName(ordOrderBatch.getToDistrict());
            addressModel.setStreetName(ordOrderBatch.getToStreet());
            addressModel.setAddress(ordOrderBatch.getToAddress());
            addressModel.setPostcode(ordOrderBatch.getToPostcode());
            addressModel.setEmail(ordOrderBatch.getToEmail());
        } else if (type.equals(CommCodes.ADDRESS_TYPE_FETCH)) {
            detailCode = ordOrderBatch.getFetchDetailCode();
            detail = ordOrderBatch.getFetchDetail();
            addressModel.setCountryName(ordOrderBatch.getFetchCountry());
            addressModel.setProvinceName(ordOrderBatch.getFetchProvince());
            addressModel.setCountryName(ordOrderBatch.getFetchCountry());
            addressModel.setCityName(ordOrderBatch.getFetchCity());
            addressModel.setDistrictName(ordOrderBatch.getFetchDistrict());
            addressModel.setStreetName(ordOrderBatch.getFetchStreet());
            addressModel.setAddress(ordOrderBatch.getFetchAddress());
            addressModel.setPostcode(ordOrderBatch.getFetchPostcode());
            addressModel.setEmail(ordOrderBatch.getFetchEmail());
        } else {
            return null;
        }
        if (org.apache.commons.lang3.StringUtils.isNotBlank(detailCode)) {
            /**
             地址冗余:地址类型|国家code|省份id|城市id|城区id|街道id|机场id，或者港口id
             cusTransportType:1|countryCode:1|provinceId:1|cityId:1|districtId:1|streetId:1|transportId:1
             **/
            Map<String, String> dataMap = this.getStringStringMap(detailCode);
            String cusTransportType = dataMap.get("cusTransportType");
            addressModel.setTransportType(StringUtils.isNumber(cusTransportType) ? Integer.parseInt(cusTransportType) : 0);
            addressModel.setCountryCode(dataMap.get("countryCode"));
            addressModel.setProvinceId(dataMap.get("provinceId"));
            addressModel.setCityId(dataMap.get("cityId"));
            if (addressModel.getTransportType() == CommCodes.TRANSPORT_LAND) {
                //速递
                addressModel.setDistrictId(dataMap.get("districtId"));
                addressModel.setStreetId(dataMap.get("streetId"));
            } else {
                //空运和海运
                addressModel.setTransportId(Integer.parseInt(dataMap.get("transportId")));
                if (addressModel.getTransportType() == CommCodes.TRANSPORT_AIR) {
                    //空运transportCode  三字码，
                    Airport port = airportService.findShortById(addressModel.getTransportId());
                    //机场三字码
                    if (null != port) {
                        addressModel.setTransportCode(port.getTriadCode());
                        addressModel.setTransportName(port.getName());
                    } else {
                        //港口不存在
                        if (CommCodes.ADDRESS_TYPE_FROM.equals(type)) {
                            addressModel.setTransportName(ordOrderBatch.getFromDistrict());
                        } else if (CommCodes.ADDRESS_TYPE_TO.equals(type)) {
                            addressModel.setTransportName(ordOrderBatch.getToDistrict());
                        }
                    }
                }
                //海运  transportEnglishName，transportCode
                else if (addressModel.getTransportType() == CommCodes.TRANSPORT_SEA) {
                    Port port = portService.findShortById(addressModel.getTransportId());
                    if (null != port) {
                        addressModel.setTransportCode(port.getCode());
                        addressModel.setTransportName(port.getName());
                        addressModel.setTransportEnglishName(port.getEnglishName());
                    } else {
                        if (CommCodes.ADDRESS_TYPE_FROM.equals(type)) {
                            addressModel.setTransportName(addressModel.getTransportName());
                        } else if (CommCodes.ADDRESS_TYPE_TO.equals(type)) {
                            addressModel.setTransportName(addressModel.getTransportName());
                        }
                    }

                }
            }
        }
        // transportTypeName

        if (org.apache.commons.lang3.StringUtils.isNotBlank(detail)) {
            String[] detailDatas = detail.split("\\|", -1);
            if (null != detailDatas && detailDatas.length >= MIN_DATA_LEN) {
                addressModel.setTransportTypeName(detailDatas[8]);
            }
        }
        return addressModel;
    }


    private String getFromDetail(OrdOrderBatch ordOrderBatch, String transportType) {
        //0联系人名称|1固定电话|2联系人电话|3国家|4省份|5城市|6区域|7街道或者港口名字或者机场名字|8运输类型|9详细地址|10邮编|11邮箱
        StringBuilder fromDetail = new StringBuilder();
        fromDetail.append(ordOrderBatch.getFromName());
        fromDetail.append(null == ordOrderBatch.getFromTelephone() ? "|" : "|" + ordOrderBatch.getFromTelephone());
        fromDetail.append(null == ordOrderBatch.getFromPhone() ? "|" : "|" + ordOrderBatch.getFromPhone());
        fromDetail.append(null == ordOrderBatch.getFromCountry() ? "|" : "|" + ordOrderBatch.getFromCountry());
        fromDetail.append(null == ordOrderBatch.getFromProvince() ? "|" : "|" + ordOrderBatch.getFromProvince());
        fromDetail.append(null == ordOrderBatch.getFromCity() ? "|" : "|" + ordOrderBatch.getFromCity());
        fromDetail.append(null == ordOrderBatch.getFromDistrict() ? "|" : "|" + ordOrderBatch.getFromDistrict());
        fromDetail.append(null == ordOrderBatch.getFromStreet() ? "|" : "|" + ordOrderBatch.getFromStreet());
        fromDetail.append(null == transportType ? "|" : "|" + transportType);
        fromDetail.append(null == ordOrderBatch.getFromAddress() ? "|" : "|" + ordOrderBatch.getFromAddress());
        fromDetail.append(null == ordOrderBatch.getFromPostcode() ? "|" : "|" + ordOrderBatch.getFromPostcode());
        fromDetail.append(null == ordOrderBatch.getFromEmail() ? "|" : "|" + ordOrderBatch.getFromEmail());
        return fromDetail.toString();
    }


    private String getToDetail(OrdOrderBatch ordOrderBatch, String transportType) {
        //0联系人名称|1固定电话|2联系人电话|3国家|4省份|5城市|6区域|7街道或者港口名字或者机场名字|8运输类型|9详细地址|10邮编|11邮箱
        StringBuilder toDetail = new StringBuilder();
        toDetail.append(ordOrderBatch.getToName());
        toDetail.append(null == ordOrderBatch.getToTelephone() ? "|" : "|" + ordOrderBatch.getToTelephone());
        toDetail.append(null == ordOrderBatch.getToPhone() ? "|" : "|" + ordOrderBatch.getToPhone());
        toDetail.append(null == ordOrderBatch.getToCountry() ? "|" : "|" + ordOrderBatch.getToCountry());
        toDetail.append(null == ordOrderBatch.getToProvince() ? "|" : "|" + ordOrderBatch.getToProvince());
        toDetail.append(null == ordOrderBatch.getToCity() ? "|" : "|" + ordOrderBatch.getToCity());
        toDetail.append(null == ordOrderBatch.getToDistrict() ? "|" : "|" + ordOrderBatch.getToDistrict());
        toDetail.append(null == ordOrderBatch.getToStreet() ? "|" : "|" + ordOrderBatch.getToStreet());
        toDetail.append(null == transportType ? "|" : "|" + transportType);
        toDetail.append(null == ordOrderBatch.getToAddress() ? "|" : "|" + ordOrderBatch.getToAddress());
        toDetail.append(null == ordOrderBatch.getToPostcode() ? "|" : "|" + ordOrderBatch.getToPostcode());
        toDetail.append(null == ordOrderBatch.getToEmail() ? "|" : "|" + ordOrderBatch.getToEmail());
        return toDetail.toString();
    }


    private String getFetchDetail(OrdOrderBatch ordOrderBatch) {
        //0联系人名称|1固定电话|2联系人电话|3国家|4省份|5城市|6区域|7街道或者港口名字或者机场名字|8运输类型|9详细地址|10邮编|11邮箱
        StringBuilder fetchDetail = new StringBuilder();
        fetchDetail.append(ordOrderBatch.getFetchName());
        fetchDetail.append(null == ordOrderBatch.getFetchTelephone() ? "|" : "|" + ordOrderBatch.getFetchTelephone());
        fetchDetail.append(null == ordOrderBatch.getFetchPhone() ? "|" : "|" + ordOrderBatch.getFetchPhone());
        fetchDetail.append(null == ordOrderBatch.getFetchCountry() ? "|" : "|" + ordOrderBatch.getFetchCountry());
        fetchDetail.append(null == ordOrderBatch.getFetchProvince() ? "|" : "|" + ordOrderBatch.getFetchProvince());
        fetchDetail.append(null == ordOrderBatch.getFetchCity() ? "|" : "|" + ordOrderBatch.getFetchCity());
        fetchDetail.append(null == ordOrderBatch.getFetchDistrict() ? "|" : "|" + ordOrderBatch.getFetchDistrict());
        fetchDetail.append(null == ordOrderBatch.getFetchStreet() ? "|" : "|" + ordOrderBatch.getFetchStreet());
        fetchDetail.append("|" + TransportTypeEnum.LAND.getName());
        fetchDetail.append(null == ordOrderBatch.getFetchDistrict() ? "|" : "|" + ordOrderBatch.getFetchDistrict());
        fetchDetail.append(null == ordOrderBatch.getFetchAddress() ? "|" : "|" + ordOrderBatch.getFetchAddress());
        fetchDetail.append(null == ordOrderBatch.getFetchPostcode() ? "|" : "|" + ordOrderBatch.getFetchPostcode());
        fetchDetail.append(null == ordOrderBatch.getFetchEmail() ? "|" : "|" + ordOrderBatch.getFetchEmail());
        return fetchDetail.toString();
    }


    /**
     * 如果当前操作人已经有批量订单数据，在数据库中先进行删掉。
     * 解析excel，
     * 1. excel的shteet数量不能为0，且要包含订单信息列表这个sheet
     * 2. 订单信息列表的sheet，列数要正确
     * 3. 订单信息列表的sheet，最多不能超过200条订单数据
     * 4.
     *
     * @param inputStream
     * @return
     * @throws IOException
     * @throws InvalidFormatException
     */
    @Override
    @Transactional
    public OrdReadResultDto readCusExcelFromStream(InputStream inputStream) throws IOException, InvalidFormatException {
        int accountId = PrincipalUtils.getAccountId();
        CusUser cusUser;
        if (accountId == 0) {
            throw Exceptions.bizException(com.sz.biz.common.constants.ErrorCodes.ERROR_COMMON, "账户登录异常");
        } else {
            cusUser = customerUserService.findById(accountId);
            if (cusUser == null) {
                //账号不存在
                throw Exceptions.bizException(com.sz.biz.common.constants.ErrorCodes.ERROR_COMMON, "账号异常");
            }
        }
        List<OrdOrderBatch> orderBatchList = Lists.newArrayList();
        long readFileTime = System.currentTimeMillis();
        OPCPackage pkg;
        XSSFWorkbook wb;
        try {
            pkg = OPCPackage.open(inputStream);
            wb = new XSSFWorkbook(pkg);
        } catch (Exception e) {
            throw Exceptions.bizException(SysErrorCodes.ERROR_FILE_ILLEGAL);
        }
        logger.info("readFileTime:" + (System.currentTimeMillis() - readFileTime));
        Sheet orderSheet = wb.getSheet(CommCodes.ORD_EXCEL_SHEET_NAME);
        //sheet不匹配
        if (null == orderSheet) {
            throw Exceptions.bizException(ErrorCodes.ERROR_ORD_EXCEL_SHEET_NOT_MATCH);
        }
        //sheet的行数,有效行
        int rows = orderSheet.getPhysicalNumberOfRows();
        //excel内容不正确
        //excel中最低需要3行数据 , 2行固定数据+1行订单数据. 下标为2
        if (rows < CommCodes.ORD_CUS_EXCEL_MIN_ROW_SIZE) {
            throw Exceptions.bizException(ErrorCodes.ERROR_ORD_EXCEL_ORDER_CONTENT_ERROR);
        }
        //sheet的列数
        Row rowOne = orderSheet.getRow(1);
        int cellSize = rowOne.getLastCellNum();
        //最低77列
        if (cellSize < CommCodes.ORD_CUS_EXCEL_MIN_COLUMN_SIZE) {
            //列数不够
            throw Exceptions.bizException(ErrorCodes.ERROR_ORD_EXCEL_ORDER_CONTENT_ERROR);
        }
        Row row0 = orderSheet.getRow(0);
        Row row1 = orderSheet.getRow(1);
        orderSheet.removeRow(row0);
        orderSheet.removeRow(row1);
        String batchNumber = UUIDGenerator.generateRandomUUID();
        long dealExcelDataTime = System.currentTimeMillis();
        for (Row row : orderSheet) {
            OrdOrderBatch orderBatch = getOrderBatch(row);
            if (null != orderBatch) {
                orderBatch.setType(CommCodes.CUSTOMER_USER_TYPE);
                orderBatch.setCusUserId(accountId);
                orderBatch.setCustomerId(cusUser.getRefCustomerId());
                orderBatch.setCreateUserId(accountId);
                orderBatchList.add(orderBatch);
                orderBatch.setBatchNumber(batchNumber);
                orderBatch.setLastUpdateUserId(accountId);
                orderBatch.setVerifiedStatus(false);
                if (StringUtils.isEmpty(orderBatch.getExternalNo())) {
                    orderBatch.setExternalNo(OrderMake.generateCusExternalNo());
                }
                //处理邮编字母转为大写
                if (!StringUtils.isEmpty(orderBatch.getFromPostcode())) {
                    orderBatch.setFromPostcode(orderBatch.getFromPostcode().toUpperCase());
                }
                if (!StringUtils.isEmpty(orderBatch.getToPostcode())) {
                    orderBatch.setToPostcode(orderBatch.getToPostcode().toUpperCase());
                }
                if (!StringUtils.isEmpty(orderBatch.getFetchPostcode())) {
                    orderBatch.setFetchPostcode(orderBatch.getFetchPostcode().toUpperCase());
                }
            }
        }
        pkg.close();
        logger.info("dealExcelDataTime" + (System.currentTimeMillis() - dealExcelDataTime));
        if (orderBatchList.size() == 0) {
            throw Exceptions.bizException(ErrorCodes.ERROR_ORD_EXCEL_ORDER_NO_DATA);
        }
        //有效数据行判断
        if (orderBatchList.size() > CommCodes.ORD_CUS_EXCEL_ORDER_MAX_SIZE) {
            throw Exceptions.bizException(ErrorCodes.ERROR_ORD_EXCEL_ORDER_NUMBER_EXCEED);
        }
        OrdReadResultDto readResultDto = new OrdReadResultDto();
        readResultDto.setBatchNumber(batchNumber);
        if (!CollectionUtils.isEmpty(orderBatchList)) {
            //先判断数据库中是否有数据，如果已经有该用户的批量数据,则先删掉之前的数据
            long dealOldDataTime = System.currentTimeMillis();
            List<String> batchNumberList = queryBatchNumbers(accountId, CommCodes.CUSTOMER_USER_TYPE);
            if (!CollectionUtils.isEmpty(batchNumberList)) {
                //数据库删除数据
                deleteByBatchNumbers(batchNumberList);
            }
            logger.info("dealOldDataTime" + (System.currentTimeMillis() - dealOldDataTime));

            long checkTime = System.currentTimeMillis();

            //校验之后得到错误条数
            readResultDto.setErrorNum(checkOrderInfo(orderBatchList, null, CommCodes.CHECK_FOR_UPLOAD_ORDER_EXCEL));
            logger.info("checkTime" + (System.currentTimeMillis() - checkTime));
            //设置国家code，供搜索用
            setExcelOrderCountryCode(orderBatchList);
            long saveTime = System.currentTimeMillis();
            saveOrderBatches(orderBatchList);
            logger.info("saveTime" + (System.currentTimeMillis() - saveTime));

        }
        //增加操作日志
        Map<String, Object> dataBackup = Maps.newHashMap();
        dataBackup.put("ADD_ORDER_BATCH_EXCEL", orderBatchList);
        PrincipalLogUtils.addOperationLog(ModuleNames.ORD, ModuleNames.ORD_ORDER_BATCH_EXCEL, UserActions.ADD, "新增excel批量订单", dataBackup);
        return readResultDto;
    }

    /**
     * 校验客户单号格式
     *
     * @param externalNo
     * @return
     */
    private Boolean checkExternalNoFormat(String externalNo) {
        //大小写英文、数字和符号“-”、“_”
        String regex = "^([\\w_\\-]+)+$";
        Pattern pattern = Pattern.compile(regex);
        Matcher m = pattern.matcher(externalNo);
        if (!m.matches()) {
            return false;
        }
        return true;
    }

    private String cutString(String value, int length) {
        if (org.apache.commons.lang3.StringUtils.isNotEmpty(value)) {
            if (value.length() > length) {
                value = value.substring(0, length);
            }
        }
        return value;
    }

    private String getValue(Cell cell) {
        String cellValue;
        switch (cell.getCellTypeEnum()) {
            case STRING:
                cellValue = cell.getRichStringCellValue().getString();
                break;
            case NUMERIC:
                DecimalFormat df = new DecimalFormat("0");
                cellValue = df.format(cell.getNumericCellValue());
                break;
            case BOOLEAN:
                cellValue = String.valueOf(cell.getBooleanCellValue());
                break;
            case FORMULA:
                cellValue = String.valueOf(cell.getCellFormula());
                break;
            case BLANK:
                cellValue = null;
                break;
            default:
                cellValue = null;
                break;
        }

        return cellValue;
    }

    private OrdOrderBatch getOrderBatch(Row row) {
        OrdOrderBatch orderBatch = new OrdOrderBatch();
        List<OrdOrderBatchCargo> cargos = Lists.newArrayList();
        OrdOrderBatchCargoList cargoList = new OrdOrderBatchCargoList();
        OrdOrderBatchCargo cargo0 = new OrdOrderBatchCargo();
        OrdOrderBatchCargo cargo1 = new OrdOrderBatchCargo();
        OrdOrderBatchCargo cargo2 = new OrdOrderBatchCargo();
        OrdOrderBatchCargo cargo3 = new OrdOrderBatchCargo();
        OrdOrderBatchCargo cargo4 = new OrdOrderBatchCargo();
        //提货地址是否同发货地址
        Boolean isFetchSameFrom = false;
        //默认是空行
        Boolean cellBlankFlag = true;
        for (Cell cell : row) {
            int columnIndex = cell.getColumnIndex();
            String cellValue = getValue(cell);
            if (!StringUtils.isEmpty(cellValue)) {
                cellBlankFlag = false;
            }
            /**
             * 客户留言140字  ---   第48列
             * 货物件数2位， --第4列
             * 客户预估重量9位，--- 第5列
             * 客户预估重量单位是2位--- 第6列
             * HS编码11位---  43,51,58,65,72
             * 商品数量9位---- 44, 52,59,66,73
             * 声明单价9位--- 46,54,61,68,75
             * 邮编15位--- 16,27,39
             * 其他30位
             */
            if (StringUtils.isEmpty(cellValue)) {
                continue;
            }
            //去特殊空格
            cellValue = cellValue.replaceAll("\\u00A0", "").trim();
            if (columnIndex == CommCodes.ORD_CUS_EXCEL_ORDER_CUSTOMERNOT_COLUMNINDEX) {
                //客户留言截取140字
                cellValue = cutString(cellValue, CommCodes.ORD_CUS_EXCEL_ORDER_CUSTOMERNOT_LENGTH);
            } else if (columnIndex == 4 || columnIndex == 6) {
                cellValue = cutString(cellValue, 2);
            } else if (columnIndex == 5 || columnIndex == 44 || columnIndex == 52 || columnIndex == 59 || columnIndex == 66 || columnIndex == 73 || columnIndex == 46 || columnIndex == 54 || columnIndex == 61 || columnIndex == 68 || columnIndex == 75) {
                cellValue = cutString(cellValue, 9);
            } else if (columnIndex == 43 || columnIndex == 51 || columnIndex == 59 || columnIndex == 66 || columnIndex == 73) {
                cellValue = cutString(cellValue, 11);
            } else if (columnIndex == 16 || columnIndex == 27 || columnIndex == 39) {
                cellValue = cutString(cellValue, 15);
            } else {
                cellValue = cutString(cellValue, 30);
            }
            switch (columnIndex) {
                /**
                 * 0~6  基本信息
                 */
                case 0:
                    /**
                     *  客户单号为空,生成一个客户单号;
                     *  客户单号不为空，限制长度30，判断规则,判断是否正确
                     */
                    orderBatch.setExternalNo(cellValue);
                    break;
                case 1:
                    /**
                     * 产品名称或者code，
                     * 名称限制30，编码限制15.这里取限制长度30，必填项目
                     */
                    orderBatch.setProductNameOrCode(cellValue);
                    break;
                case 2:
                    /**
                     * 是否揽收
                     */
                    if (org.apache.commons.lang3.StringUtils.isEmpty(cellValue)) {
                        cellValue = "否";
                    }
                    orderBatch.setFetchFlag("是".equals(cellValue) ? true : false);
                    break;
                case 3:
                    /**
                     * 货物类型，最长30
                     */
                    orderBatch.setCargoType(cellValue);
                    break;
                case 4:
                    /**
                     *货物件数,1到99
                     */
                    orderBatch.setPackageNum(cellValue);
                    break;
                case 5:
                    /**
                     * 货物总重，
                     */
                    orderBatch.setCusWeight(cellValue);
                    break;
                case 6:
                    /**
                     * 货物重量单位
                     */
                    orderBatch.setCusWeightUnit(cellValue);
                    break;
                /**
                 *7~17 发件地址
                 *
                 */
                case 7:
                    /**
                     *发件人姓名，上限30字
                     */
                    orderBatch.setFromName(cellValue);
                    break;
                case 8:
                    /**
                     * 发件人国家
                     */
                    orderBatch.setFromCountry(cellValue);
                    break;
                case 9:
                    /**
                     * 发件人的省份,
                     */
                    orderBatch.setFromProvince(cellValue);
                    break;
                case 10:
                    /**
                     * 发件人城市
                     */
                    orderBatch.setFromCity(cellValue);
                    break;
                case 11:
                    /**
                     * 发件人*区县/机场/港口
                     */
                    orderBatch.setFromDistrict(cellValue);
                    break;
                case 12:
                    /**
                     * 发件人街道
                     */
                    orderBatch.setFromStreet(cellValue);
                    break;
                case 13:
                    /**
                     * 发件人地址
                     */
                    orderBatch.setFromAddress(cellValue);
                    break;
                case 14:
                    /**
                     * 发件人移动电话
                     */
                    orderBatch.setFromPhone(cellValue);
                    break;
                case 15:
                    /**
                     * 发件人固定电话
                     */
                    orderBatch.setFromTelephone(cellValue);
                    break;
                case 16:
                    /**
                     * 邮编
                     */
                    orderBatch.setFromPostcode(cellValue);
                    break;
                case 17:
                    /**
                     * 电子邮箱
                     */
                    orderBatch.setFromEmail(cellValue);
                    break;
                /**
                 * 18~28 收件人地址
                 */
                case 18:
                    /**
                     *收件人姓名，上限30字
                     */
                    orderBatch.setToName(cellValue);
                    break;
                case 19:
                    /**
                     * 收件人国家
                     */
                    orderBatch.setToCountry(cellValue);
                    break;
                case 20:
                    /**
                     * 收件人的省份,
                     */
                    orderBatch.setToProvince(cellValue);
                    break;
                case 21:
                    /**
                     * 收件人城市
                     */
                    orderBatch.setToCity(cellValue);
                    break;
                case 22:
                    /**
                     * 发件人*区县/机场/港口
                     */
                    orderBatch.setToDistrict(cellValue);
                    break;
                case 23:
                    /**
                     * 收件人街道
                     */
                    orderBatch.setToStreet(cellValue);
                    break;
                case 24:
                    /**
                     * 收件人地址
                     */
                    orderBatch.setToAddress(cellValue);
                    break;
                case 25:
                    /**
                     * 收件人移动电话
                     */
                    orderBatch.setToPhone(cellValue);
                    break;
                case 26:
                    /**
                     * 收件人固定电话
                     */
                    orderBatch.setToTelephone(cellValue);
                    break;
                case 27:
                    /**
                     * 收件人邮编
                     */
                    orderBatch.setToPostcode(cellValue);
                    break;
                case 28:
                    /**
                     * 收件人电子邮箱
                     */
                    orderBatch.setToEmail(cellValue);
                    break;
                /**
                 * 29~40  提货地址
                 */
                case 29:
                    /**
                     * 提货地址是否同发件人地址
                     */
                    if (org.apache.commons.lang3.StringUtils.isEmpty(cellValue)) {
                        cellValue = "否";
                    }
                    isFetchSameFrom = "是".equals(cellValue);
                    break;
                case 30:
                    /**
                     * 提货人姓名
                     */
                    //当有提货服务时，看是否和发件人一样
                    if (isFetchSameFrom) {
                        //和发件人一样
                        cellValue = orderBatch.getFromName();
                    }
                    orderBatch.setFetchName(cellValue);
                    break;
                case 31:
                    /**
                     * 提货人国家
                     */
                    if (isFetchSameFrom) {
                        cellValue = orderBatch.getFromCountry();
                    }
                    orderBatch.setFetchCountry(cellValue);
                    break;
                case 32:
                    /**
                     * 提货人省份
                     */
                    if (isFetchSameFrom) {
                        cellValue = orderBatch.getFromProvince();
                    }
                    orderBatch.setFetchProvince(cellValue);
                    break;
                case 33:
                    /**
                     * 提货人城市
                     */
                    if (isFetchSameFrom) {
                        cellValue = orderBatch.getFromCity();
                    }
                    orderBatch.setFetchCity(cellValue);
                    break;
                case 34:
                    /**
                     * 提货人*区县/机场/港口
                     */
                    if (isFetchSameFrom) {
                        cellValue = orderBatch.getFromDistrict();

                    }
                    orderBatch.setFetchDistrict(cellValue);
                    break;
                case 35:
                    /**
                     * 提货人街道
                     */
                    if (isFetchSameFrom) {
                        cellValue = orderBatch.getFromStreet();
                    }
                    orderBatch.setFetchStreet(cellValue);
                    break;
                case 36:
                    /**
                     * 提货人地址
                     */
                    //需要提货
                    if (isFetchSameFrom) {
                        cellValue = orderBatch.getFromAddress();
                    }
                    orderBatch.setFetchAddress(cellValue);
                    break;
                case 37:
                    /**
                     * 提货人移动电话
                     */
                    if (isFetchSameFrom) {
                        cellValue = orderBatch.getFromPhone();
                    }
                    orderBatch.setFetchPhone(cellValue);
                    break;
                case 38:
                    /**
                     * 提货人固定电话
                     */
                    if (isFetchSameFrom) {
                        cellValue = orderBatch.getFromTelephone();
                    }
                    orderBatch.setFetchTelephone(cellValue);
                    break;
                case 39:
                    /**
                     * 提货人邮编
                     */
                    if (isFetchSameFrom) {
                        cellValue = orderBatch.getFromPostcode();
                    }
                    orderBatch.setFetchPostcode(cellValue);
                    break;
                case 40:
                    /**
                     * 提货人电子邮箱
                     */
                    if (isFetchSameFrom) {
                        cellValue = orderBatch.getFromEmail();
                    }
                    orderBatch.setFetchEmail(cellValue);
                    break;
                /**
                 * 41~47 物品明细1
                 */
                case 41:
                    /**
                     * 物品名称0
                     */
                    cargo0.setGoodsNameCn(cellValue);
                    break;
                case 42:
                    /**
                     * 物品英文名称0
                     */

                    cargo0.setGoodsNameEn(cellValue);
                    break;
                case 43:
                    /**
                     * 物品0的hs编码
                     */
                    cargo0.setHsCode(cellValue);
                    break;
                case 44:
                    /**
                     * 物品0的数量
                     */
                    cargo0.setGoodsNumber(cellValue);
                    break;
                case 45:
                    /**
                     * 物品0的计量单位
                     */
                    cargo0.setGoodsUnitName(cellValue);
                    break;
                case 46:
                    /**
                     * 物品0的声明单价
                     */
                    cargo0.setGoodsPrice(cellValue);
                    break;
                case 47:
                    /**
                     * 物品0的描述
                     */
                    cargo0.setDescription(cellValue);
                    break;
                case 48:
                    /**
                     * 客户留言
                     */
                    orderBatch.setCustomerNote(cellValue);
                    break;
                /**
                 * 49~55物品明细2
                 */
                case 49:
                    /**
                     * 物品名称0
                     */
                    cargo1.setGoodsNameCn(cellValue);
                    break;
                case 50:
                    /**
                     * 物品英文名称0
                     */
                    cargo1.setGoodsNameEn(cellValue);
                    break;
                case 51:
                    /**
                     * 物品0的hs编码
                     */
                    cargo1.setHsCode(cellValue);
                    break;
                case 52:
                    /**
                     * 物品0的数量
                     */
                    cargo1.setGoodsNumber(cellValue);
                    break;
                case 53:
                    /**
                     * 物品0的计量单位
                     */
                    cargo1.setGoodsUnitName(cellValue);
                    break;
                case 54:
                    /**
                     * 物品0的声明单价
                     */
                    cargo1.setGoodsPrice(cellValue);
                    break;
                case 55:
                    /**
                     * 物品0的描述
                     */
                    cargo1.setDescription(cellValue);
                    break;

                /**
                 * 56~62 物品明细3
                 */
                case 56:
                    /**
                     * 物品名称0
                     */
                    cargo2.setGoodsNameCn(cellValue);
                    break;
                case 57:
                    /**
                     * 物品英文名称0
                     */
                    cargo2.setGoodsNameEn(cellValue);
                    break;
                case 58:
                    /**
                     * 物品3的hs编码
                     */
                    cargo2.setHsCode(cellValue);
                    break;
                case 59:
                    /**
                     * 物品0的数量
                     */
                    cargo2.setGoodsNumber(cellValue);
                    break;
                case 60:
                    /**
                     * 物品0的计量单位
                     */
                    cargo2.setGoodsUnitName(cellValue);
                    break;
                case 61:
                    /**
                     * 物品0的声明单价
                     */
                    cargo2.setGoodsPrice(cellValue);
                    break;
                case 62:
                    /**
                     * 物品0的描述
                     */
                    cargo2.setDescription(cellValue);
                    break;
                /**
                 * 63~69  物品明细4
                 */
                case 63:
                    /**
                     * 物品名称0
                     */
                    cargo3.setGoodsNameCn(cellValue);
                    break;
                case 64:
                    /**
                     * 物品英文名称0
                     */
                    cargo3.setGoodsNameEn(cellValue);
                    break;
                case 65:
                    /**
                     * 物品0的hs编码
                     */
                    cargo3.setHsCode(cellValue);
                    break;
                case 66:
                    /**
                     * 物品0的数量
                     */
                    cargo3.setGoodsNumber(cellValue);
                    break;
                case 67:
                    /**
                     * 物品0的计量单位
                     */
                    cargo3.setGoodsUnitName(cellValue);
                    break;
                case 68:
                    /**
                     * 物品0的声明单价
                     */
                    cargo3.setGoodsPrice(cellValue);
                    break;
                case 69:
                    /**
                     * 物品0的描述
                     */
                    cargo3.setDescription(cellValue);
                    break;
                /**
                 * 70~76  物品明细5
                 */
                case 70:
                    /**
                     * 物品名称0
                     */
                    cargo4.setGoodsNameCn(cellValue);
                    break;
                case 71:
                    /**
                     * 物品英文名称0
                     */
                    cargo4.setGoodsNameEn(cellValue);
                    break;
                case 72:
                    /**
                     * 物品0的hs编码
                     */
                    cargo4.setHsCode(cellValue);
                    break;
                case 73:
                    /**
                     * 物品0的数量
                     */
                    cargo4.setGoodsNumber(cellValue);
                    break;
                case 74:
                    /**
                     * 物品0的计量单位
                     */
                    cargo4.setGoodsUnitName(cellValue);
                    break;
                case 75:
                    /**
                     * 物品0的声明单价
                     */
                    cargo4.setGoodsPrice(cellValue);
                    break;
                case 76:
                    /**
                     * 物品0的描述
                     */
                    cargo4.setDescription(cellValue);
                    break;
                default:
                    break;
            }
        }

        //处理是否揽收
        if (null == orderBatch.getFetchFlag()) {
            orderBatch.setFetchFlag(false);
        }
        //处理提货人地址
        if (isFetchSameFrom) {
            /**
             * 提货人姓名
             */
            orderBatch.setFetchName(orderBatch.getFromName());
            /**
             * 提货人国家
             */
            orderBatch.setFetchCountry(orderBatch.getFromCountry());
            /**
             * 提货人省份
             */
            orderBatch.setFetchProvince(orderBatch.getFromProvince());
            /**
             * 提货人城市
             */
            orderBatch.setFetchCity(orderBatch.getFromCity());
            /**
             * 提货人*区县/机场/港口
             */
            orderBatch.setFetchDistrict(orderBatch.getFromDistrict());
            /**
             * 提货人街道
             */
            orderBatch.setFetchStreet(orderBatch.getFromStreet());
            /**
             * 提货人地址
             */
            orderBatch.setFetchAddress(orderBatch.getFromAddress());
            /**
             * 提货人固定电话
             */
            orderBatch.setFetchTelephone(orderBatch.getFromTelephone());
            /**
             * 提货人移动电话
             */
            orderBatch.setFetchPhone(orderBatch.getFromPhone());
            /**
             * 提货人邮编
             */
            orderBatch.setFetchPostcode(orderBatch.getFromPostcode());
            /**
             * 提货人电子邮箱
             */
            orderBatch.setFetchEmail(orderBatch.getFromEmail());

        }


        if (cellBlankFlag) {
            return null;
        }
        if (!com.sz.common.base.utils.ObjectUtils.checkFieldValueNull(cargo0)) {
            cargos.add(cargo0);
        }
        if (!com.sz.common.base.utils.ObjectUtils.checkFieldValueNull(cargo1)) {
            cargos.add(cargo1);
        }
        if (!com.sz.common.base.utils.ObjectUtils.checkFieldValueNull(cargo2)) {
            cargos.add(cargo2);
        }
        if (!com.sz.common.base.utils.ObjectUtils.checkFieldValueNull(cargo3)) {
            cargos.add(cargo3);
        }
        if (!com.sz.common.base.utils.ObjectUtils.checkFieldValueNull(cargo4)) {
            cargos.add(cargo4);
        }
        cargoList.setCargos(cargos);
        orderBatch.setGoodsDetail(JsonUtils.toJSONString(cargoList));


        return orderBatch;
    }

    /**
     * 上传文件时，客户单号的校验
     *
     * @param ordOrderBatch
     * @param lstExternalNo
     * @param errorCode2msg
     * @return
     */
    private boolean checkExternalNoInfo(OrdOrderBatch ordOrderBatch, List<String> lstExternalNo, Map<String, OrdOrderBatchErrorDto> errorCode2msg) {
        String externalNo = ordOrderBatch.getExternalNo();
        OrdOrderBatchErrorDto errorDto = new OrdOrderBatchErrorDto();
        if (!this.checkExternalNoFormat(externalNo)) {
            errorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            errorDto.setMessage("请输入大小写字母、数字或符号-、_");
            errorCode2msg.put("externalNo", errorDto);
            return false;
        } else if (lstExternalNo.contains(externalNo)) {

            List<String> sameExternalNos = Lists.newArrayList();
            lstExternalNo.forEach(item -> {
                if (externalNo.equals(item)) {
                    sameExternalNos.add(item);
                }
            });
            if (null == ordOrderBatch.getId()) {
                errorDto.setErrorCode(ErrorCodes.ERROR_COMMON.getCode());
                errorDto.setMessage("客户单号已存在");
                errorCode2msg.put("externalNo", errorDto);
                return false;
            } else {
                //非add
                if (sameExternalNos.size() > 1) {
                    errorDto.setErrorCode(ErrorCodes.ERROR_COMMON.getCode());
                    errorDto.setMessage("客户单号已存在");
                    errorCode2msg.put("externalNo", errorDto);
                    return false;
                }
            }


        }

        return true;
    }

    private void checkExternalNoInfoForDetail(OrdOrderBatch ordOrderBatch, List<String> lstExternalNo, Map<String, OrdOrderBatchErrorDto> errorCode2msg) {
        String externalNo = ordOrderBatch.getExternalNo();
        OrdOrderBatchErrorDto errorDto = new OrdOrderBatchErrorDto();
        if (!this.checkExternalNoFormat(externalNo)) {
            errorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            errorDto.setMessage("请输入大小写字母、数字或符号-、_");
            errorCode2msg.put("externalNo", errorDto);
        } else if (lstExternalNo.contains(externalNo)) {
            List<String> sameExternalNos = Lists.newArrayList();
            lstExternalNo.forEach(item -> {
                if (externalNo.equals(item)) {
                    sameExternalNos.add(item);
                }
            });
            if (sameExternalNos.size() > 1) {
                errorDto.setErrorCode(ErrorCodes.ERROR_COMMON.getCode());
                errorDto.setMessage("客户单号已存在");
                errorCode2msg.put("externalNo", errorDto);
            }
        }
    }

    /**
     * 校验客户单号 唯一性
     *
     * @param externalNo
     * @param custormerID
     * @return
     */
    private boolean checkExternalNo(String externalNo, Integer custormerID) {

        if (null == custormerID || StringUtils.isEmpty(externalNo)) {
            return false;
        }
        String custormerId = String.valueOf(custormerID);
        List<String> lstExternalNo = dao.findForList(getSqlName("findAllExternalNoByCusID"), custormerId, String.class);
        if (lstExternalNo.contains(externalNo)) {
            List<String> sameExternalNos = Lists.newArrayList();
            lstExternalNo.forEach(item -> {
                if (externalNo.equals(item)) {
                    sameExternalNos.add(item);
                }
            });
            if (sameExternalNos.size() > 1) {
                return false;
            }
        }
        return true;

    }


    /**
     * 详情中，校验批量下单中不通过的数据的错误详情
     *
     * @param lstExcelOrderData
     * @return
     */

    private List<Map<String, OrdOrderBatchErrorDto>> getBatchOrderFailDetail(List<OrdOrderBatch> lstExcelOrderData) {
        List<Map<String, OrdOrderBatchErrorDto>> lstFailDetail = Lists.newArrayList();
        this.checkOrderInfoForDetail(lstExcelOrderData, lstFailDetail);
        return lstFailDetail;
    }

    /**
     * 保存时，校验批量下单中不通过的数据的错误信息
     *
     * @param lstExcelOrderData
     * @return
     */

    private Map<String, OrdOrderBatchErrorDto> getBatchOrderFailInfoForSave(List<OrdOrderBatch> lstExcelOrderData) {
        List<Map<String, OrdOrderBatchErrorDto>> lstFailDetail = Lists.newArrayList();
        Map<String, OrdOrderBatchErrorDto> field2FailDetail = Maps.newHashMap();
        checkOrderInfo(lstExcelOrderData, lstFailDetail, CommCodes.CHECK_FOR_UPDATE);
        if (!CollectionUtils.isEmpty(lstFailDetail)) {
            field2FailDetail = lstFailDetail.get(0);
        }
        return field2FailDetail;
    }

    private List<String> getExcelAllExternalNo(List<OrdOrderBatch> lstExcelOrderData) {
        List<String> excelExternalNo = Lists.newArrayList();
        for (OrdOrderBatch ordOrderBatch : lstExcelOrderData) {
            if (org.apache.commons.lang3.StringUtils.isNotBlank(ordOrderBatch.getExternalNo())) {
                excelExternalNo.add(ordOrderBatch.getExternalNo());
            }
        }
        return excelExternalNo;
    }

    /**
     * 根据Excel批量查找产品信息
     *
     * @param lstExcelOrderData
     * @return
     */
    public Map<String, List<Product>> getExcelProductInfo(List<OrdOrderBatch> lstExcelOrderData) {
        Integer custormerId = lstExcelOrderData.get(0).getCustomerId();
        List<String> lstProductNameOrCode = Lists.newArrayList();
        for (OrdOrderBatch ordOrderBatch : lstExcelOrderData) {
            String productNameOrCode = getProductCodeOfOrderBatch(ordOrderBatch);
            if (!StringUtils.isEmpty(productNameOrCode) && !lstProductNameOrCode.contains(productNameOrCode)) {
                lstProductNameOrCode.add(productNameOrCode);
            }
        }
        Map<String, List<Product>> nameOrCode2ProductMap = Maps.newHashMap();
        if (lstProductNameOrCode.size() > 0) {
            List<Product> lstProductInfo = productService.findProductInfoByNameOrCodeList(lstProductNameOrCode, custormerId);
            for (String nameOrCode : lstProductNameOrCode) {
                for (Product product : lstProductInfo) {
                    if (nameOrCode.equals(product.getName()) || nameOrCode.equals(product.getCode())) {
                        if (null == nameOrCode2ProductMap.get(nameOrCode)) {
                            nameOrCode2ProductMap.put(nameOrCode, Lists.newArrayList());
                        }
                        nameOrCode2ProductMap.get(nameOrCode).add(product);
                    }
                }
            }
        }

        return nameOrCode2ProductMap;
    }

    @Override
    public int checkOrderInfo(List<OrdOrderBatch> lstExcelOrderData, List<Map<String, OrdOrderBatchErrorDto>> errorMapList, String checkType) {
        //1. 校验 客户单号的唯一性
        //2. 校验 产品对应的信息:货物类型，货物重量，附件服务
        //3. 校验 地址 信息
        //1659
        //4. 校验 物品信息
        int notPassData = 0;
        String custormerId = String.valueOf(lstExcelOrderData.get(0).getCustomerId());
        List<String> lstExternalNo = dao.findForList(getSqlName("findAllExternalNoByCusID"), custormerId, String.class);
        if (null == errorMapList) {
            errorMapList = Lists.newArrayList();
        }
        List<String> lstExcelExternalNo = getExcelAllExternalNo(lstExcelOrderData);
        //Excel中产品名称或code与产品的对应关系
        Map<String, List<Product>> nameOrCode2lstProductMap = getExcelProductInfo(lstExcelOrderData);
        for (OrdOrderBatch ordOrderBatch : lstExcelOrderData) {
            Map<String, OrdOrderBatchErrorDto> errorCode2Msg = Maps.newHashMap();
            // 处理fromdetail，todetail，fetchdetail
            //发件人地址冗余:0联系人名称|1固定电话|2联系人电话|3国家|4省份|5城市|6区域|7街道或者港口名字或者机场名字|8运输类型|9详细地址|10邮编|11邮箱
            ordOrderBatch.setFromDetail(getFromDetail(ordOrderBatch, null));
            ordOrderBatch.setToDetail(getToDetail(ordOrderBatch, null));
            ordOrderBatch.setFetchDetail(getFetchDetail(ordOrderBatch));
            String externalNo = ordOrderBatch.getExternalNo();
            boolean flag = true;
            if (ordOrderBatch.getVerifiedStatus()) {
                continue;
            }
            //校验产品信息
            if (!checkProductInfo(ordOrderBatch, errorCode2Msg, nameOrCode2lstProductMap)) {
                ordOrderBatch.setVerifiedStatus(false);
                errorMapList.add(errorCode2Msg);
                notPassData++;
                flag = false;
                continue;
            }
            //校验 客户单号的唯一性
            if (!checkExternalNoInfo(ordOrderBatch, lstExternalNo, errorCode2Msg)) {
                flag = false;
                errorMapList.add(errorCode2Msg);
                notPassData++;
                continue;
            }
            //如果是上传excel中的校验，则需要先看客户单号在excel中的重复
            if (checkType.equals(CommCodes.CHECK_FOR_UPLOAD_ORDER_EXCEL)) {
                int count = Collections.frequency(lstExcelExternalNo, externalNo);
                if (count > 1) {
                    flag = false;
                    OrdOrderBatchErrorDto errorDto = new OrdOrderBatchErrorDto();
                    errorDto.setErrorCode(ErrorCodes.ERROR_COMMON.getCode());
                    errorDto.setMessage("客户单号已存在");
                    errorCode2Msg.put("externalNo", errorDto);
                    errorMapList.add(errorCode2Msg);
                    notPassData++;
                    continue;
                }
            }
            //校验 物品信息，物品明细必须有一条数据
            String goodsDetail = ordOrderBatch.getGoodsDetail();
            if (!StringUtils.isEmpty(goodsDetail)) {
                OrdOrderBatchCargoList cargoList = JsonUtils.toObject(goodsDetail, OrdOrderBatchCargoList.class);
                if (null != cargoList) {
                    List<OrdOrderBatchCargo> goods = cargoList.getCargos();
                    if (!CollectionUtils.isEmpty(goods)) {
                        if (!this.checkGoodInfo(goods, errorCode2Msg)) {
                            cargoList.setCargos(goods);
                            ordOrderBatch.setGoodsDetail(JsonUtils.toJSONString(cargoList));
                            ordOrderBatch.setVerifiedStatus(false);
                            notPassData++;
                            errorMapList.add(errorCode2Msg);
                            flag = false;
                            continue;
                        }
                        cargoList.setCargos(goods);
                        ordOrderBatch.setGoodsDetail(JsonUtils.toJSONString(cargoList));
                    } else {
                        OrdOrderBatchErrorDto errorDto = new OrdOrderBatchErrorDto();
                        errorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
                        String keyStr = "cargos";
                        errorCode2Msg.put(keyStr, errorDto);
                        errorMapList.add(errorCode2Msg);
                        ordOrderBatch.setVerifiedStatus(false);
                        flag = false;
                        notPassData++;
                        continue;
                    }
                }
            }
            ordOrderBatch.setVerifiedStatus(flag);
        }
        return notPassData;
    }

    @Override
    public void checkOrderInfoForDetail(List<OrdOrderBatch> lstExcelOrderData, List<Map<String, OrdOrderBatchErrorDto>> errorMapList) {
        //1. 校验 客户单号的唯一性
        //2. 校验 产品对应的信息:货物类型，货物重量，附件服务
        //3. 校验 地址 信息
        //4. 校验 物品信息
        String custormerId = String.valueOf(lstExcelOrderData.get(0).getCustomerId());
        List<String> lstExternalNo = dao.findForList(getSqlName("findAllExternalNoByCusID"), custormerId, String.class);
        if (null == errorMapList) {
            errorMapList = Lists.newArrayList();
        }
        Map<String, OrdOrderBatchErrorDto> errorCode2Msg = Maps.newHashMap();

        for (OrdOrderBatch ordOrderBatch : lstExcelOrderData) {
            //校验产品信息
            this.checkProductInfoForDetail(ordOrderBatch, errorCode2Msg);
            //校验 客户单号的唯一性
            this.checkExternalNoInfoForDetail(ordOrderBatch, lstExternalNo, errorCode2Msg);
            //校验 物品信息
            String goodsDetail = ordOrderBatch.getGoodsDetail();
            if (org.apache.commons.lang3.StringUtils.isNotBlank(goodsDetail)) {
                OrdOrderBatchCargoList cargoList = JsonUtils.toObject(goodsDetail, OrdOrderBatchCargoList.class);
                if (null != cargoList) {
                    List<OrdOrderBatchCargo> goods = cargoList.getCargos();
                    if (!CollectionUtils.isEmpty(goods)) {
                        this.checkGoodInfoForDetail(goods, errorCode2Msg);
                        cargoList.setCargos(goods);
                        String newGoodsDetail = JsonUtils.toJSONString(cargoList);
                        ordOrderBatch.setGoodsDetail(newGoodsDetail);

                        if (!goodsDetail.equals(newGoodsDetail)) {
                            updateCargos(ordOrderBatch);
                        }
                    } else {
                        //货物明细为空
                        OrdOrderBatchErrorDto errorDto = new OrdOrderBatchErrorDto();
                        errorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
                        String keyStr = "cargos";
                        errorCode2Msg.put(keyStr, errorDto);
                    }

                }

            }

            if (!CollectionUtils.isEmpty(errorCode2Msg)) {
                errorMapList.add(errorCode2Msg);
            }
        }
    }

    private void checkProductInfoForDetail(OrdOrderBatch ordOrderBatch, Map<String, OrdOrderBatchErrorDto> errorCode2Msg) {
        if (null == errorCode2Msg) {
            errorCode2Msg = Maps.newHashMap();
        }
        //必填项：产品名称或编码
        OrdOrderBatchErrorDto productErrorDto = new OrdOrderBatchErrorDto();
        if (StringUtils.isEmpty(ordOrderBatch.getProductNameOrCode())) {
            productErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            productErrorDto.setMessage("产品不能为空");
            errorCode2Msg.put("productName", productErrorDto);
        }
        //先看冗余数据中是否有产品code
        String productNameOrCode = getProductCodeOfOrderBatch(ordOrderBatch);
        if (StringUtils.isEmpty(productNameOrCode)) {
            return;
        }
        List<Product> lstProduct = productService.findProductInfoByNameOrCode(productNameOrCode, ordOrderBatch.getCustomerId());
        if (lstProduct.size() == 1) {
            Product product = lstProduct.get(0);
            ordOrderBatch.setProductNameOrCode(product.getName());
            ordOrderBatch.setRedundanceData("productCode:" + product.getCode() + "|productId:" + product.getId() + "|productUid:" + product.getUid() + "|productGroupLeafId:" + product.getProductGroupLeafId());
            //校验产品的 运输类型（全球海运:1，全球空运:6，全球速递:11）
            boolean isSudi = true;
            String transportType = null;
            ProductGroupInfo productGroupInfo = productService.getProductGroupById(product.getId());
            if (CommCodes.TRANSPORT_SEA == productGroupInfo.getProductGroupRootId()) {
                isSudi = false;
                transportType = String.valueOf(CommCodes.TRANSPORT_SEA);
            } else if (CommCodes.TRANSPORT_AIR == productGroupInfo.getProductGroupRootId()) {
                isSudi = false;
                transportType = String.valueOf(CommCodes.TRANSPORT_AIR);
            } else {
                isSudi = true;
                transportType = String.valueOf(CommCodes.TRANSPORT_LAND);
            }
            //校验产品对应的货物类型信息
            this.cargoInfoCheckForDtail(product, ordOrderBatch, errorCode2Msg);
            ordOrderBatch.setRedundanceData(ordOrderBatch.getRedundanceData() + "|transportType:" + transportType);
            //校驗产品 是否有揽收服务:如果产品有揽收服务，将揽收服务的CODE赋值给AdditionalTypeCode，如果没有，则不处理Excel该字段数据
            boolean isHasFetch = this.isFetchCheck(product, ordOrderBatch);
            //校验地址信息：发件人地址信息，收件人地址信息，揽收地址信息，服务范围,详细地址
            this.checkExcelAddressInfoForDetail(ordOrderBatch, transportType, isSudi, isHasFetch, product.getUid(), errorCode2Msg);
            //更新fromdetailcode  todetailcode fetchdetailcode
            updateDetailCode(ordOrderBatch);
            //校验 联系人移动电话，固定电话，邮编，电子邮箱//校验发件人姓名，收件人姓名，揽收人姓名
            boolean fromContact = this.checkFromContactInfo(ordOrderBatch, errorCode2Msg);
            boolean toContact = this.checkToContactInfo(ordOrderBatch, errorCode2Msg);
            if (isHasFetch) {
                boolean fetchContact = this.checkFetchContactInfo(ordOrderBatch, errorCode2Msg);
            }
        } else {
            productErrorDto.setErrorCode(ErrorCodes.ERROR_COMMON.getCode());
            productErrorDto.setMessage("产品不存在");
            errorCode2Msg.put("productName", productErrorDto);
        }
    }


    private String getProductCodeOfOrderBatch(OrdOrderBatch ordOrderBatch) {
        Map<String, String> redundanceDataMap = getStringStringMap(ordOrderBatch.getRedundanceData());
        String productNameOrCode = ordOrderBatch.getProductNameOrCode();
        if (!StringUtils.isEmpty(redundanceDataMap.get("productCode"))) {
            productNameOrCode = redundanceDataMap.get("productCode");
        }
        return productNameOrCode;
    }

    private boolean checkProductInfo(OrdOrderBatch ordOrderBatch, Map<String, OrdOrderBatchErrorDto> errorCode2Msg, Map<String, List<Product>> nameOrCode2lstProductMap) {
        if (null == errorCode2Msg) {
            errorCode2Msg = Maps.newHashMap();
        }
        //必填项：产品名称或编码
        OrdOrderBatchErrorDto productErrorDto = new OrdOrderBatchErrorDto();
        if (StringUtils.isEmpty(ordOrderBatch.getProductNameOrCode())) {
            productErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            productErrorDto.setMessage("产品不能为空");
            errorCode2Msg.put("productName", productErrorDto);
            return false;
        }
        String productNameOrCode = getProductCodeOfOrderBatch(ordOrderBatch);
        //List<Product> lstProduct = productService.findProductInfoByNameOrCode(productNameOrCode, ordOrderBatch.getCustomerId());
        List<Product> lstProduct = nameOrCode2lstProductMap.get(productNameOrCode);
        if (!CollectionUtils.isEmpty(lstProduct) && lstProduct.size() == 1) {
            Product product = lstProduct.get(0);
            ordOrderBatch.setProductNameOrCode(product.getName());
            ordOrderBatch.setRedundanceData("productCode:" + product.getCode() + "|productId:" + product.getId() + "|productUid:" + product.getUid() + "|productGroupLeafId:" + product.getProductGroupLeafId());
            //校验产品的 运输类型（全球海运:1，全球空运:6，全球速递:11）
            boolean isSudi;
            String transportType;
            ProductGroupInfo productGroupInfo = productService.getProductGroupById(product.getId());
            if (CommCodes.TRANSPORT_SEA == productGroupInfo.getProductGroupRootId() || CommCodes.TRANSPORT_AIR == productGroupInfo.getProductGroupRootId()) {
                //空运或者海运
                isSudi = false;
                transportType = String.valueOf(productGroupInfo.getProductGroupRootId());
            } else {
                //速运
                isSudi = true;
                transportType = String.valueOf(CommCodes.TRANSPORT_LAND);
            }
            //校驗产品 是否有揽收服务:如果产品有揽收服务，将揽收服务的CODE赋值给AdditionalTypeCode，如果没有，则不处理Excel该字段数据
            boolean isHasFetch = this.isFetchCheck(product, ordOrderBatch);
            //根据产品的类型和揽收，处理有效数据，清除无效数据
            processAddress(ordOrderBatch, transportType, isHasFetch);
            ordOrderBatch.setRedundanceData(ordOrderBatch.getRedundanceData() + "|transportType:" + transportType);
            //校验产品对应的货物类型信息
            boolean cargoCheckResult = this.cargoInfoCheck(product, ordOrderBatch, productErrorDto, errorCode2Msg);
            if (!cargoCheckResult) {
                return false;
            }
            //校验地址信息：发件人地址信息，收件人地址信息，揽收地址信息，服务范围
            boolean addressValid = this.checkExcelAddressInfo(ordOrderBatch, transportType, isSudi, isHasFetch, product.getUid(), errorCode2Msg);
            //校验 联系人移动电话，固定电话，邮编，电子邮箱//校验发件人姓名，收件人姓名，揽收人姓名
            boolean fromContact = this.checkFromContactInfo(ordOrderBatch, errorCode2Msg);
            if (!fromContact || !addressValid) {
                return false;
            }
            boolean toContact = this.checkToContactInfo(ordOrderBatch, errorCode2Msg);
            if (!toContact || !addressValid) {
                return false;
            }
            if (isHasFetch) {
                boolean fetchContact = this.checkFetchContactInfo(ordOrderBatch, errorCode2Msg);
                if (!fetchContact || !addressValid) {
                    return false;
                }
            }
        } else {
            productErrorDto.setErrorCode(ErrorCodes.ERROR_COMMON.getCode());
            productErrorDto.setMessage("产品不存在");
            errorCode2Msg.put("productName", productErrorDto);
            return false;
        }
        return true;
    }

    /**
     * 根据产品的类型，处理地址有效数据.
     * 如果产品是速递，则只保留速递的有效地址。
     * 如果是产品是空运，则只保留空运的有效地址
     * 如果产品是海运，则只保留海运的有效地址.
     * 处理揽货地址。 揽货地址当前只为速递地址，  判断是否真的有揽货，如果有则处理，如果没有则不处理。
     *
     * @param ordOrderBatch
     * @param transportType
     * @param isNeedFetch   是否需要揽收地址
     */
    private void processAddress(OrdOrderBatch ordOrderBatch, String transportType, Boolean isNeedFetch) {
        if (StringUtils.isEmpty(transportType)) {
            return;
        }
        if (transportType.equals(String.valueOf(CommCodes.TRANSPORT_SEA)) || transportType.equals(String.valueOf(CommCodes.TRANSPORT_AIR))) {
            //空运或者海运
            ordOrderBatch.setFromProvince(null);
            ordOrderBatch.setFromStreet(null);
            ordOrderBatch.setFromAddress(null);
            ordOrderBatch.setToProvince(null);
            ordOrderBatch.setToStreet(null);
            ordOrderBatch.setToAddress(null);
        }
        if (!isNeedFetch) {
            //不需要提货地址
            ordOrderBatch.setFetchName(null);
            ordOrderBatch.setFetchTelephone(null);
            ordOrderBatch.setFetchPhone(null);
            ordOrderBatch.setFetchCountry(null);
            ordOrderBatch.setFetchProvince(null);
            ordOrderBatch.setFetchCity(null);
            ordOrderBatch.setFetchDistrict(null);
            ordOrderBatch.setFetchStreet(null);
            ordOrderBatch.setFetchAddress(null);
            ordOrderBatch.setFetchPostcode(null);
            ordOrderBatch.setFetchEmail(null);
        }
    }


    private boolean isFetchCheck(Product product, OrdOrderBatch ordOrderBatch) {
        boolean isHasFetch = false;
        boolean batchFetchFlag = ordOrderBatch.getFetchFlag();
        ProductReceiveInfoDto productReceiveInfoDto = productService.findProductReceiveInfoByUid(product.getUid());
        //查询产品的服务里面是否有提货服务。//主服务和必选服务中是否有提货服务.
        boolean bOk = productReceiveInfoDto.isProductReceive();
        //判断可选服务中是否有揽收
        List<ServiceTypeReceiveInfo> receiveTypeInfoList = productReceiveInfoDto.getServiceTypeReceiveInfo();
        boolean additionalFetchFlag = false;
        if (!CollectionUtils.isEmpty(receiveTypeInfoList)) {
            for (ServiceTypeReceiveInfo serviceTypeReceiveInfo : receiveTypeInfoList) {
                if (serviceTypeReceiveInfo.isServiceReceive()) {
                    additionalFetchFlag = true;
                    break;
                }
            }
        }
        //当主服务，必选服务中有揽收， 或者可选服务类型中有揽收类型，则表示这个产品有揽收.
        if (bOk || (additionalFetchFlag && batchFetchFlag)) {
            isHasFetch = true;
        }
        //客户选择了附加服务类型中的揽收服务类型，同时产品的附加服务类型确实有揽收服务类型，同时AdditionalTypeCode中没有包含揽收类型的code，做AdditionalTypeCode处理。
        if (batchFetchFlag && additionalFetchFlag) {
            if (StringUtils.isEmpty(ordOrderBatch.getAdditionalTypeCode())) {
                ordOrderBatch.setAdditionalTypeCode(OrderStatusToServiceTypeEnum.RECEGOOD.getName());
            } else {
                if (!ordOrderBatch.getAdditionalTypeCode().contains(OrderStatusToServiceTypeEnum.RECEGOOD.getName())) {
                    ordOrderBatch.setAdditionalTypeCode(ordOrderBatch.getAdditionalTypeCode() + "|" + OrderStatusToServiceTypeEnum.RECEGOOD.getName());
                }
            }
        }
        return isHasFetch;
    }

    private boolean cargoInfoCheck(Product product, OrdOrderBatch ordOrderBatch, OrdOrderBatchErrorDto productErrorDto, Map<String, OrdOrderBatchErrorDto> errorCode2Msg) {
        if (ObjectUtils.isEmpty(productErrorDto)) {
            productErrorDto = new OrdOrderBatchErrorDto();
        }
        if (null == errorCode2Msg) {
            errorCode2Msg = Maps.newHashMap();
        }
        String cargoType = ordOrderBatch.getCargoType();
        List<ProductCargotypeRelDto> cargotypeRelDtos = productCargoTypeRelService.findByProductId(product.getId());
        List<String> cargotypeNames = Lists.newArrayList();
        Map<String, String> cargoTypeName2CodeMap = Maps.newHashMap();
        for (ProductCargotypeRelDto productCargotypeRelDto : cargotypeRelDtos) {
            cargotypeNames.add(productCargotypeRelDto.getCargoTypeName());
            cargoTypeName2CodeMap.put(productCargotypeRelDto.getCargoTypeName(), productCargotypeRelDto.getCargoTypeCode());
        }
        //设置 redundanceData值：例如productUid:23437478374234|cargoType:GT001
        //  String redundanceData = "productId:" + product.getId() + "|" + "productUid:" + product.getUid();
        //必填项：货物类型
        if (StringUtils.isEmpty(cargoType)) {
            // ordOrderBatch.setRedundanceData(redundanceData);
            productErrorDto.setErrorCode(ErrorCodes.ERROR_COMMON.getCode());
            errorCode2Msg.put("cargoType", productErrorDto);
            return false;
        }
        if (!cargotypeNames.contains(cargoType)) {
            // ordOrderBatch.setRedundanceData(redundanceData);
            productErrorDto.setErrorCode(ErrorCodes.ERROR_COMMON.getCode());
            productErrorDto.setMessage("产品的货物类型不存在");
            errorCode2Msg.put("cargoType", productErrorDto);
            return false;
        }
        String redundanceCargoType = "cargoType:" + cargoTypeName2CodeMap.get(cargoType);
        if (StringUtils.isEmpty(ordOrderBatch.getRedundanceData())) {
            ordOrderBatch.setRedundanceData(redundanceCargoType);
        } else {
            ordOrderBatch.setRedundanceData(ordOrderBatch.getRedundanceData() + "|" + redundanceCargoType);
        }
        //必填项：重量单位
        if (StringUtils.isEmpty(ordOrderBatch.getCusWeightUnit())) {
            productErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            errorCode2Msg.put("cusWeightUnit", productErrorDto);
            return false;
        }

        //校验 产品的重量单位(code去匹配)和范围
        Map<String, String> sysDictUnitBaseMap = sysDictService.findMapByCatalog(CommCodes.SYS_DICT_BIZ_UNIT_WEIGHT);
        if (CollectionUtils.isEmpty(sysDictUnitBaseMap) || null == sysDictUnitBaseMap.get(ordOrderBatch.getCusWeightUnit())) {
            productErrorDto.setErrorCode(ErrorCodes.ERROR_COMMON.getCode());
            productErrorDto.setMessage("产品的货物重量单位不存在");
            errorCode2Msg.put("cusWeightUnit", productErrorDto);
            return false;
        }

        //必填项：预估重量
        if (StringUtils.isEmpty(ordOrderBatch.getCusWeight())) {
            productErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            errorCode2Msg.put("cusWeight", productErrorDto);
            return false;
        }
        String cusWeight = ordOrderBatch.getCusWeight();

        Map<String, Map<String, String>> regex2infoMap = this.getCheckRegex();
        Map<String, String> mapRegex = regex2infoMap.get("regex");
        Map<String, String> regex2tip = regex2infoMap.get("tip");
        String regexCusWeight = mapRegex.get("cusWeight");
        if (!checkFieldValid(regexCusWeight, cusWeight)) {
            productErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            productErrorDto.setMessage(regex2tip.get(regexCusWeight));
            errorCode2Msg.put("cusWeight", productErrorDto);
            return false;
        }
        BigDecimal cusWeightd = new BigDecimal(cusWeight);
        WeightDto weightDto = new WeightDto(cusWeightd, ordOrderBatch.getCusWeightUnit());
        ResultDto result = productService.checkWeight(product.getUid(), weightDto);
        if (result.getData().equals(false)) {
            productErrorDto.setErrorCode(ErrorCodes.ERROR_COMMON.getCode());
            productErrorDto.setMessage(result.getMsg());
            errorCode2Msg.put("cusWeight", productErrorDto);
            return false;
        }
        String packageNum = ordOrderBatch.getPackageNum();
        //必填项：货物件数
        if (StringUtils.isEmpty(packageNum)) {
            productErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            errorCode2Msg.put("packageNum", productErrorDto);
            return false;
        }
        //校验 货物件数 1-99
        if (!StringUtils.isNumber(packageNum)) {
            productErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            productErrorDto.setMessage("请输入2位正整数");
            errorCode2Msg.put("packageNum", productErrorDto);
            return false;
        }

        if (Integer.valueOf(packageNum) < CommCodes.PACKAGE_MIN_NUM || Integer.valueOf(packageNum) > CommCodes.PACKAGE_MAX_NUM) {
            productErrorDto.setErrorCode(ErrorCodes.ERROR_COMMON.getCode());
            productErrorDto.setMessage("请输入2位正整数");
            errorCode2Msg.put("packageNum", productErrorDto);
            return false;
        }
        return true;
    }

    private void cargoInfoCheckForDtail(Product product, OrdOrderBatch ordOrderBatch, Map<String, OrdOrderBatchErrorDto> errorCode2Msg) {
        if (null == errorCode2Msg) {
            errorCode2Msg = Maps.newHashMap();
        }
        String cargoType = ordOrderBatch.getCargoType();

        List<ProductCargotypeRelDto> cargotypeRelDtos = productCargoTypeRelService.findByProductId(product.getId());
        List<String> cargotypeNames = Lists.newArrayList();
        Map<String, String> cargoTypeName2CodeMap = Maps.newHashMap();
        for (ProductCargotypeRelDto productCargotypeRelDto : cargotypeRelDtos) {
            cargotypeNames.add(productCargotypeRelDto.getCargoTypeName());
            cargoTypeName2CodeMap.put(productCargotypeRelDto.getCargoTypeName(), productCargotypeRelDto.getCargoTypeCode());
        }
        //设置 redundanceData值：例如productUid:23437478374234|cargoType:GT001
        // String redundanceData = "productId:" + product.getId() + "|" + "productUid:" + product.getUid();

        //必填项：货物类型
        if (StringUtils.isEmpty(cargoType)) {
            OrdOrderBatchErrorDto productErrorDto = new OrdOrderBatchErrorDto();
            // ordOrderBatch.setRedundanceData(redundanceData);
            productErrorDto.setErrorCode(ErrorCodes.ERROR_COMMON.getCode());
            errorCode2Msg.put("cargoType", productErrorDto);
        } else if (!cargotypeNames.contains(cargoType)) {
            OrdOrderBatchErrorDto productErrorDto = new OrdOrderBatchErrorDto();
            // ordOrderBatch.setRedundanceData(redundanceData);
            productErrorDto.setErrorCode(ErrorCodes.ERROR_COMMON.getCode());
            productErrorDto.setMessage("产品的货物类型不存在");
            errorCode2Msg.put("cargoType", productErrorDto);
        }
        String redundanceCargoType = "cargoType:" + cargoTypeName2CodeMap.get(cargoType);
        if (StringUtils.isEmpty(ordOrderBatch.getRedundanceData())) {
            ordOrderBatch.setRedundanceData(redundanceCargoType);
        } else {
            ordOrderBatch.setRedundanceData(ordOrderBatch.getRedundanceData() + "|" + redundanceCargoType);
        }
        //必填项：货物重量
        if (StringUtils.isEmpty(ordOrderBatch.getCusWeight())) {
            OrdOrderBatchErrorDto productErrorDto = new OrdOrderBatchErrorDto();
            productErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            errorCode2Msg.put("cusWeight", productErrorDto);
        }
        //必填项：重量单位
        if (StringUtils.isEmpty(ordOrderBatch.getCusWeightUnit())) {
            OrdOrderBatchErrorDto productErrorDto = new OrdOrderBatchErrorDto();
            productErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            errorCode2Msg.put("cusWeightUnit", productErrorDto);
        } else {
            //校验 产品的重量单位(code去匹配)和范围
            Map<String, String> sysDictUnitBaseMap = sysDictService.findMapByCatalog(CommCodes.SYS_DICT_BIZ_UNIT_WEIGHT);
            if (CollectionUtils.isEmpty(sysDictUnitBaseMap) || null == sysDictUnitBaseMap.get(ordOrderBatch.getCusWeightUnit())) {
                //产品的重量单位不存在
                OrdOrderBatchErrorDto productErrorDto = new OrdOrderBatchErrorDto();
                productErrorDto.setErrorCode(ErrorCodes.ERROR_COMMON.getCode());
                productErrorDto.setMessage("产品的货物重量单位不存在");
                errorCode2Msg.put("cusWeightUnit", productErrorDto);
            } else {
                //产品单位存在了，去校验重量
                if (!StringUtils.isEmpty(ordOrderBatch.getCusWeight())) {
                    String cusWeight = ordOrderBatch.getCusWeight();
                    Map<String, Map<String, String>> regex2infoMap = this.getCheckRegex();
                    Map<String, String> mapRegex = regex2infoMap.get("regex");
                    Map<String, String> regex2tip = regex2infoMap.get("tip");
                    String regexCusWeight = mapRegex.get("cusWeight");
                    if (!checkFieldValid(regexCusWeight, cusWeight)) {
                        OrdOrderBatchErrorDto productErrorDto = new OrdOrderBatchErrorDto();
                        productErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
                        productErrorDto.setMessage(regex2tip.get(regexCusWeight));
                        errorCode2Msg.put("cusWeight", productErrorDto);
                    } else {
                        BigDecimal cusWeightd = new BigDecimal(cusWeight);
                        WeightDto weightDto = new WeightDto(cusWeightd, ordOrderBatch.getCusWeightUnit());
                        ResultDto result = productService.checkWeight(product.getUid(), weightDto);
                        if (result.getData().equals(false)) {
                            OrdOrderBatchErrorDto productErrorDto = new OrdOrderBatchErrorDto();
                            productErrorDto.setErrorCode(ErrorCodes.ERROR_COMMON.getCode());
                            //productErrorDto.setMessage("产品的货物重量不在范围之内");
                            productErrorDto.setMessage(result.getMsg());
                            errorCode2Msg.put("cusWeight", productErrorDto);
                        }
                    }
                }

            }
        }


        String packageNum = ordOrderBatch.getPackageNum();
        //必填项：货物件数
        if (StringUtils.isEmpty(packageNum)) {
            OrdOrderBatchErrorDto productErrorDto = new OrdOrderBatchErrorDto();
            productErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            errorCode2Msg.put("packageNum", productErrorDto);
        } else if (!StringUtils.isNumber(packageNum)) {
            //校验 货物件数 1-99
            OrdOrderBatchErrorDto productErrorDto = new OrdOrderBatchErrorDto();
            productErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            productErrorDto.setMessage("请输入2位正整数");
            errorCode2Msg.put("packageNum", productErrorDto);
        } else if (Integer.valueOf(packageNum) < CommCodes.PACKAGE_MIN_NUM || Integer.valueOf(packageNum) > CommCodes.PACKAGE_MAX_NUM) {
            OrdOrderBatchErrorDto productErrorDto = new OrdOrderBatchErrorDto();
            productErrorDto.setErrorCode(ErrorCodes.ERROR_COMMON.getCode());
            productErrorDto.setMessage("请输入2位正整数");
            errorCode2Msg.put("packageNum", productErrorDto);
        }
    }

    //校验发件人联系固定电话和联系电话，邮编，邮箱
    private boolean checkFromContactInfo(OrdOrderBatch orderBatch, Map<String, OrdOrderBatchErrorDto> errorCode2Msg) {

        Map<String, Map<String, String>> regex2infoMap = this.getCheckRegex();
        //字段对应的正则表达式
        Map<String, String> mapRegex = regex2infoMap.get("regex");
        //正则表达式对应的提示信息
        Map<String, String> regex2tip = regex2infoMap.get("tip");
        String regexName = mapRegex.get("NAME");
        String fromName = orderBatch.getFromName();
        //必填项：发件人姓名

        if (StringUtils.isEmpty(fromName)) {
            OrdOrderBatchErrorDto contacErrorDto = new OrdOrderBatchErrorDto();
            contacErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            errorCode2Msg.put("fromName", contacErrorDto);

        } else if (!checkFieldValid(regexName, fromName)) {
            OrdOrderBatchErrorDto contacErrorDto = new OrdOrderBatchErrorDto();
            contacErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            contacErrorDto.setMessage(regex2tip.get(regexName));
            errorCode2Msg.put("fromName", contacErrorDto);
        }

        String regexPhone = mapRegex.get("PHONE");
        String fromPhone = orderBatch.getFromPhone();
        String fromTelephone = orderBatch.getFromTelephone();
        if (StringUtils.isEmpty(fromPhone) && StringUtils.isEmpty(fromTelephone)) {
            OrdOrderBatchErrorDto contacErrorDto = new OrdOrderBatchErrorDto();
            contacErrorDto.setErrorCode(ErrorCodes.ERROR_COMMON.getCode());
            //contacErrorDto.setMessage("发件人固定电话和联系电话至少需要一个");
            String keyStr = "fromPhone";

            errorCode2Msg.put(keyStr, contacErrorDto);
        }
        if (!StringUtils.isEmpty(fromPhone) && !checkFieldValid(regexPhone, fromPhone)) {
            OrdOrderBatchErrorDto contacErrorDto = new OrdOrderBatchErrorDto();
            contacErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());

            contacErrorDto.setMessage(regex2tip.get(regexPhone));
            String keyStr = "fromPhone";
            errorCode2Msg.put(keyStr, contacErrorDto);
        }
        if (!StringUtils.isEmpty(fromTelephone) && !checkFieldValid(regexPhone, fromTelephone)) {
            OrdOrderBatchErrorDto contacErrorDto = new OrdOrderBatchErrorDto();
            contacErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            //contacErrorDto.setMessage("发件人固定电话不合法");
            contacErrorDto.setMessage(regex2tip.get(regexPhone));
            String keyStr = "fromTelephone";
            errorCode2Msg.put(keyStr, contacErrorDto);
        }
        String fromPostcode = orderBatch.getFromPostcode();
        String regexFromPostcode = mapRegex.get("IMOCODE");
        //邮编为必填项目
        if (StringUtils.isEmpty(fromPostcode)) {
            OrdOrderBatchErrorDto contacErrorDto = new OrdOrderBatchErrorDto();
            contacErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            String keyStr = "fromPostcode";
            errorCode2Msg.put(keyStr, contacErrorDto);
        } else if (!StringUtils.isEmpty(fromPostcode) && !checkFieldValid(regexFromPostcode, fromPostcode)) {
            OrdOrderBatchErrorDto contacErrorDto = new OrdOrderBatchErrorDto();
            contacErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            contacErrorDto.setMessage(regex2tip.get(regexFromPostcode));
            String keyStr = "fromPostcode";
            errorCode2Msg.put(keyStr, contacErrorDto);
        }
        String fromEmail = orderBatch.getFromEmail();
        String regexFromEmail = mapRegex.get("EMAIL");
        if (!StringUtils.isEmpty(fromEmail) && !checkFieldValid(regexFromEmail, fromEmail)) {
            OrdOrderBatchErrorDto contacErrorDto = new OrdOrderBatchErrorDto();
            contacErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            contacErrorDto.setMessage(regex2tip.get(regexFromEmail));
            String keyStr = "fromEmail";
            errorCode2Msg.put(keyStr, contacErrorDto);
        }
        if (!CollectionUtils.isEmpty(errorCode2Msg) && errorCode2Msg.size() > 1) {
            return false;
        }
        return true;
    }

    //校验揽收人联系固定电话和联系电话，邮编，邮箱
    private boolean checkFetchContactInfo(OrdOrderBatch orderBatch, Map<String, OrdOrderBatchErrorDto> errorCode2Msg) {

        Map<String, Map<String, String>> regex2infoMap = this.getCheckRegex();
        //字段对应的正则表达式
        Map<String, String> mapRegex = regex2infoMap.get("regex");
        //正则表达式对应的提示信息

        Map<String, String> regex2tip = regex2infoMap.get("tip");
        String regexName = mapRegex.get("NAME");
        String fetchName = orderBatch.getFetchName();
        //必填项：揽收人姓名
        if (StringUtils.isEmpty(fetchName)) {
            OrdOrderBatchErrorDto contacErrorDto = new OrdOrderBatchErrorDto();
            contacErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            errorCode2Msg.put("fetchName", contacErrorDto);
        } else if (!this.checkFieldValid(regexName, fetchName)) {
            OrdOrderBatchErrorDto contacErrorDto = new OrdOrderBatchErrorDto();
            contacErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            contacErrorDto.setMessage(regex2tip.get(regexName));
            errorCode2Msg.put("fetchName", contacErrorDto);
        }
        String regexPhone = mapRegex.get("PHONE");
        String fetchPhone = orderBatch.getFetchPhone();
        String fetchTelephone = orderBatch.getFetchTelephone();
        if (StringUtils.isEmpty(fetchPhone) && StringUtils.isEmpty(fetchTelephone)) {
            OrdOrderBatchErrorDto contacErrorDto = new OrdOrderBatchErrorDto();
            contacErrorDto.setErrorCode(ErrorCodes.ERROR_COMMON.getCode());
            //contacErrorDto.setMessage("揽收人固定电话和联系电话至少需要一个");
            String keyStr = "fetchPhone";

            errorCode2Msg.put(keyStr, contacErrorDto);
        }
        if (!StringUtils.isEmpty(fetchPhone) && !checkFieldValid(regexPhone, fetchPhone)) {
            OrdOrderBatchErrorDto contacErrorDto = new OrdOrderBatchErrorDto();
            contacErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            contacErrorDto.setMessage(regex2tip.get(regexPhone));
            String keyStr = "fetchPhone";
            errorCode2Msg.put(keyStr, contacErrorDto);
        }
        if (!StringUtils.isEmpty(fetchTelephone) && !checkFieldValid(regexPhone, fetchTelephone)) {
            OrdOrderBatchErrorDto contacErrorDto = new OrdOrderBatchErrorDto();
            contacErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            contacErrorDto.setMessage(regex2tip.get(regexPhone));
            String keyStr = "fetchTelephone";
            errorCode2Msg.put(keyStr, contacErrorDto);
        }
        String fetchPostcode = orderBatch.getFetchPostcode();
        String regexFetchPostcode = mapRegex.get("IMOCODE");
        //邮编为必填项目
        if (StringUtils.isEmpty(fetchPostcode)) {
            OrdOrderBatchErrorDto contacErrorDto = new OrdOrderBatchErrorDto();
            contacErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            String keyStr = "fetchPostcode";
            errorCode2Msg.put(keyStr, contacErrorDto);
        } else if (!StringUtils.isEmpty(fetchPostcode) && !checkFieldValid(regexFetchPostcode, fetchPostcode)) {
            OrdOrderBatchErrorDto contacErrorDto = new OrdOrderBatchErrorDto();
            contacErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            //contacErrorDto.setMessage("揽收人邮编不合法");
            contacErrorDto.setMessage(regex2tip.get(regexFetchPostcode));
            String keyStr = "fetchPostcode";
            errorCode2Msg.put(keyStr, contacErrorDto);
        }
        String fetchEmail = orderBatch.getFetchEmail();
        String regexFetchEmail = mapRegex.get("EMAIL");
        if (!StringUtils.isEmpty(fetchEmail) && !checkFieldValid(regexFetchEmail, fetchEmail)) {
            OrdOrderBatchErrorDto contacErrorDto = new OrdOrderBatchErrorDto();
            contacErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            contacErrorDto.setMessage(regex2tip.get(regexFetchEmail));
            String keyStr = "fetchEmail";
            errorCode2Msg.put(keyStr, contacErrorDto);
        }
        if (!CollectionUtils.isEmpty(errorCode2Msg) && errorCode2Msg.size() > 0) {
            return false;
        }
        return true;
    }

    //校验收件人联系固定电话和联系电话，邮编，邮箱
    private boolean checkToContactInfo(OrdOrderBatch orderBatch, Map<String, OrdOrderBatchErrorDto> errorCode2Msg) {

        Map<String, Map<String, String>> regex2infoMap = this.getCheckRegex();
        Map<String, String> mapRegex = regex2infoMap.get("regex");
        Map<String, String> regex2tip = regex2infoMap.get("tip");
        String regexName = mapRegex.get("NAME");
        String toName = orderBatch.getToName();
        //必填项：揽收人姓名

        if (StringUtils.isEmpty(toName)) {
            OrdOrderBatchErrorDto contacErrorDto = new OrdOrderBatchErrorDto();
            contacErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            errorCode2Msg.put("toName", contacErrorDto);
        } else if (!this.checkFieldValid(regexName, toName)) {
            OrdOrderBatchErrorDto contacErrorDto = new OrdOrderBatchErrorDto();
            contacErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            contacErrorDto.setMessage(regex2tip.get(regexName));
            errorCode2Msg.put("toName", contacErrorDto);
        }

        String regexPhone = mapRegex.get("PHONE");
        String toPhone = orderBatch.getToPhone();
        String toTelephone = orderBatch.getToTelephone();
        if (StringUtils.isEmpty(toPhone) && StringUtils.isEmpty(toTelephone)) {
            OrdOrderBatchErrorDto contacErrorDto = new OrdOrderBatchErrorDto();
            contacErrorDto.setErrorCode(ErrorCodes.ERROR_COMMON.getCode());
            //contacErrorDto.setMessage("收件人固定电话和联系电话至少需要一个");
            String keyStr = "toPhone";
            errorCode2Msg.put(keyStr, contacErrorDto);
        }
        if (!StringUtils.isEmpty(toPhone) && !checkFieldValid(regexPhone, toPhone)) {
            OrdOrderBatchErrorDto contacErrorDto = new OrdOrderBatchErrorDto();
            contacErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            contacErrorDto.setMessage(regex2tip.get(regexPhone));
            String keyStr = "toPhone";
            errorCode2Msg.put(keyStr, contacErrorDto);
        }
        if (!StringUtils.isEmpty(toTelephone) && !checkFieldValid(regexPhone, toTelephone)) {
            OrdOrderBatchErrorDto contacErrorDto = new OrdOrderBatchErrorDto();
            contacErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            contacErrorDto.setMessage(regex2tip.get(regexPhone));
            String keyStr = "toTelephone";
            errorCode2Msg.put(keyStr, contacErrorDto);
        }
        String toPostcode = orderBatch.getToPostcode();
        String regexToPostcode = mapRegex.get("IMOCODE");
        //邮编为必填项目
        if (StringUtils.isEmpty(toPostcode)) {
            OrdOrderBatchErrorDto contacErrorDto = new OrdOrderBatchErrorDto();
            contacErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            String keyStr = "toPostcode";
            errorCode2Msg.put(keyStr, contacErrorDto);
        } else if (!checkFieldValid(regexToPostcode, toPostcode)) {
            OrdOrderBatchErrorDto contacErrorDto = new OrdOrderBatchErrorDto();
            contacErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            contacErrorDto.setMessage(regex2tip.get(regexToPostcode));
            String keyStr = "toPostcode";
            errorCode2Msg.put(keyStr, contacErrorDto);
        }
        String toEmail = orderBatch.getToEmail();
        String regextoEmail = mapRegex.get("EMAIL");
        if (!StringUtils.isEmpty(toEmail) && !checkFieldValid(regextoEmail, toEmail)) {
            OrdOrderBatchErrorDto contacErrorDto = new OrdOrderBatchErrorDto();
            contacErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            contacErrorDto.setMessage(regex2tip.get(regextoEmail));
            String keyStr = "toEmail";
            errorCode2Msg.put(keyStr, contacErrorDto);
        }
        if (!CollectionUtils.isEmpty(errorCode2Msg)) {
            return false;
        }
        return true;
    }

    //校验所有物品信息
    private boolean checkGoodInfo(List<OrdOrderBatchCargo> ordOrderBatchCargos, Map<String, OrdOrderBatchErrorDto> errorCode2Msg) {
        int fieldsCountTest = this.getFieldCount(OrdOrderBatchCargo.class);
        for (int i = 0; i < ordOrderBatchCargos.size(); i++) {
            if (this.checkVanGood(ordOrderBatchCargos.get(i), fieldsCountTest)) {
                continue;
            }
            if (!this.checkOneGoodInfo(ordOrderBatchCargos.get(i), i, errorCode2Msg)) {
                return false;
            }
        }
        return true;
    }

    private void checkGoodInfoForDetail(List<OrdOrderBatchCargo> ordOrderBatchCargos, Map<String, OrdOrderBatchErrorDto> errorCode2Msg) {
        int fieldsCountTest = this.getFieldCount(OrdOrderBatchCargo.class);
        for (int i = 0; i < ordOrderBatchCargos.size(); i++) {
            if (this.checkVanGood(ordOrderBatchCargos.get(i), fieldsCountTest)) {
                continue;
            }
            this.checkOneGoodInfoForDetail(ordOrderBatchCargos.get(i), i, errorCode2Msg);
        }
    }

    //读取空物品信息
    private boolean checkVanGood(OrdOrderBatchCargo ordOrderBatchCargo, int fieldCount) {
        int vanCount = 0;
        String goodsNameCn = ordOrderBatchCargo.getGoodsNameCn();
        if (StringUtils.isEmpty(goodsNameCn)) {
            vanCount++;
        }
        String goodsNameEn = ordOrderBatchCargo.getGoodsNameEn();
        if (StringUtils.isEmpty(goodsNameEn)) {
            vanCount++;
        }
        String hsCode = ordOrderBatchCargo.getHsCode();
        if (StringUtils.isEmpty(hsCode)) {
            vanCount++;
        }
        String goodsNumber = ordOrderBatchCargo.getGoodsNumber();
        if (StringUtils.isEmpty(goodsNumber)) {
            vanCount++;
        }
        String goodsUnit = ordOrderBatchCargo.getGoodsUnit();
        if (StringUtils.isEmpty(goodsUnit)) {
            vanCount++;
        }
        String goodsPrice = ordOrderBatchCargo.getGoodsPrice();
        if (StringUtils.isEmpty(goodsPrice)) {
            vanCount++;
        }
        String description = ordOrderBatchCargo.getDescription();
        if (StringUtils.isEmpty(description)) {
            vanCount++;
        }
        if (vanCount == fieldCount) {
            return true;
        }
        return false;
    }

    private int getFieldCount(Class<?> clazz) {
        Field[] fields = clazz.getDeclaredFields();
        int count = fields.length;
        return count;
    }

    private Map<String, Object> getFieldName2Value(OrdOrderBatchCargo ordOrderBatchCargo) {
        Map<String, Object> field2Value = Maps.newHashMap();
        Class clazz = ordOrderBatchCargo.getClass();
        Field[] fields = clazz.getDeclaredFields();
        List<String> fieldNameList = Lists.newArrayList();
        try {
            for (int i = 0; i < fields.length; i++) {
                Field f = fields[i];
                f.setAccessible(true); // 设置些属性是可以访问的
                Object val = f.get(ordOrderBatchCargo); // 得到此属性的值
                fieldNameList.add(fields[i].getName());
                field2Value.put(fields[i].getName(), val);
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return field2Value;
    }

    //校验单个物品信息
    private boolean checkOneGoodInfo(OrdOrderBatchCargo ordOrderBatchCargo, int index, Map<String, OrdOrderBatchErrorDto> errorCode2Msg) {
        //处理goodunit ,由goodsUnitName得goodsUnit
        processOrderCargoUnit(ordOrderBatchCargo);
        Map<String, Object> field2ValueMap = this.getFieldName2Value(ordOrderBatchCargo);
        Map<String, Map<String, String>> regex2infoMap = this.getCheckRegex();
        Map<String, String> mapRegex = regex2infoMap.get("regex");
        Map<String, String> regex2tip = regex2infoMap.get("tip");
        for (Map.Entry<String, Object> entry : field2ValueMap.entrySet()) {
            String fieldName = entry.getKey();
            String fieldValue = null;
            if (null != entry.getValue()) {
                fieldValue = String.valueOf(entry.getValue());
            }
            String regexField = mapRegex.get(fieldName);
            String keyStr = fieldName + index;
            if (!checkFieldValid(regexField, fieldValue)) {
                OrdOrderBatchErrorDto goodErrorDto = new OrdOrderBatchErrorDto();
                goodErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
                if (fieldName.equals("goodsUnit")) {
                    keyStr = "goodsUnitName" + index;
                    goodErrorDto.setMessage("物品计量单位不合法");
                } else {
                    goodErrorDto.setMessage(regex2tip.get(regexField));
                }
                errorCode2Msg.put(keyStr, goodErrorDto);
                return false;
            }
            if ("hsCode".equals(fieldName) && StringUtils.isNumber(fieldValue) && fieldValue.length() > CommCodes.HSCODE_MAX_LEN) {
                OrdOrderBatchErrorDto goodErrorDto = new OrdOrderBatchErrorDto();
                goodErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
                //单位不正确
                goodErrorDto.setMessage(regex2tip.get(regexField));
                errorCode2Msg.put(keyStr, goodErrorDto);
                return false;
            }
            if ("goodsUnitName".equals(fieldName)) {
                //判断物品计量单位的值是否正确
                if (StringUtils.isEmpty(ordOrderBatchCargo.getGoodsUnit())) {
                    OrdOrderBatchErrorDto goodErrorDto = new OrdOrderBatchErrorDto();
                    goodErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
                    //单位不正确
                    goodErrorDto.setMessage("物品计量单位不合法");
                    errorCode2Msg.put(keyStr, goodErrorDto);
                    return false;
                }
            }
        }
        return true;
    }

    private void checkOneGoodInfoForDetail(OrdOrderBatchCargo ordOrderBatchCargo, int index, Map<String, OrdOrderBatchErrorDto> errorCode2Msg) {
        //处理goodunit ,由goodsUnitName得goodsUnit
        processOrderCargoUnit(ordOrderBatchCargo);
        Map<String, Object> field2ValueMap = this.getFieldName2Value(ordOrderBatchCargo);
        Map<String, Map<String, String>> regex2infoMap = this.getCheckRegex();
        Map<String, String> mapRegex = regex2infoMap.get("regex");
        Map<String, String> regex2tip = regex2infoMap.get("tip");
        for (
                Map.Entry<String, Object> entry : field2ValueMap.entrySet()) {
            String fieldName = entry.getKey();
            String fieldValue = null;
            if (null != entry.getValue()) {
                fieldValue = String.valueOf(entry.getValue());
            }
            String regexField = mapRegex.get(fieldName);
            OrdOrderBatchErrorDto goodErrorDto = new OrdOrderBatchErrorDto();
            goodErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            String keyStr = fieldName + index;
            if (StringUtils.isEmpty(fieldValue)) {
                if ("goodsUnit".equals(fieldName)) {
                    //单位不正确
                    goodErrorDto.setMessage("物品计量单位不合法");
                    errorCode2Msg.put("goodsUnitName" + index, goodErrorDto);
                } else {
                    goodErrorDto.setMessage(null);
                    errorCode2Msg.put(keyStr, goodErrorDto);
                }
            } else if (!checkFieldValid(regexField, fieldValue)) {
                goodErrorDto.setMessage(regex2tip.get(regexField));
                errorCode2Msg.put(keyStr, goodErrorDto);
            } else {
                if ("hsCode".equals(fieldName) && StringUtils.isNumber(fieldValue) && fieldValue.length() > CommCodes.HSCODE_MAX_LEN) {
                    goodErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
                    //单位不正确
                    goodErrorDto.setMessage(regex2tip.get(regexField));
                    errorCode2Msg.put(keyStr, goodErrorDto);
                }
            }
            if ("goodsUnitName".equals(fieldName) && !checkFieldValid(regexField, fieldValue)) {
                //判断物品计量单位的值是否正确
                if (StringUtils.isEmpty(ordOrderBatchCargo.getGoodsUnit())) {
                    //单位不正确
                    if (!errorCode2Msg.containsKey(keyStr)) {
                        goodErrorDto.setMessage("物品计量单位不合法");
                        errorCode2Msg.put(keyStr, goodErrorDto);
                    }
                }
            }
        }
    }


    private void processOrderCargoUnit(OrdOrderBatchCargo ordOrderBatchCargo) {
        if (StringUtils.isEmpty(ordOrderBatchCargo.getGoodsUnit())) {
            Map<String, String> sysDictUnitBaseMap = sysDictService.findMapByCatalog(CommCodes.SYS_DICT_BIZ_UNIT_BASE);
            if (!CollectionUtils.isEmpty(sysDictUnitBaseMap)) {
                sysDictUnitBaseMap.forEach((k, v) -> {
                    if (null != v && v.equals(ordOrderBatchCargo.getGoodsUnitName())) {
                        ordOrderBatchCargo.setGoodsUnit(k);
                        return;
                    }
                });
            }
        }

    }

    //校验字段值是否为空
    private void checkOneGoodInfoForVanData(OrdOrderBatchCargo ordOrderBatchCargo, int index, Map<String, OrdOrderBatchErrorDto> errorCode2Msg) {
        String goodNameCn = ordOrderBatchCargo.getGoodsNameCn();
        if (StringUtils.isEmpty(goodNameCn)) {
            OrdOrderBatchErrorDto goodErrorDto = new OrdOrderBatchErrorDto();
            goodErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            String keyStr = "goodsNameCn" + index;
            errorCode2Msg.put(keyStr, goodErrorDto);
        }
        String goodNameEn = ordOrderBatchCargo.getGoodsNameEn();
        if (StringUtils.isEmpty(goodNameEn)) {
            OrdOrderBatchErrorDto goodErrorDto = new OrdOrderBatchErrorDto();
            goodErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            String keyStr = "goodsNameEn" + index;
            errorCode2Msg.put(keyStr, goodErrorDto);
        }
        String hsCode = ordOrderBatchCargo.getHsCode();
        if (StringUtils.isEmpty(hsCode)) {
            OrdOrderBatchErrorDto goodErrorDto = new OrdOrderBatchErrorDto();
            goodErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            String keyStr = "hsCode" + index;
            errorCode2Msg.put(keyStr, goodErrorDto);
        }
        String goodsNumber = ordOrderBatchCargo.getGoodsNumber();
        if (StringUtils.isEmpty(goodsNumber)) {
            OrdOrderBatchErrorDto goodErrorDto = new OrdOrderBatchErrorDto();
            goodErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            String keyStr = "goodsNumber" + index;
            errorCode2Msg.put(keyStr, goodErrorDto);
        }
        String goodsUnitName = ordOrderBatchCargo.getGoodsUnitName();
        if (StringUtils.isEmpty(goodsUnitName)) {
            OrdOrderBatchErrorDto goodErrorDto = new OrdOrderBatchErrorDto();
            goodErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            String keyStr = "goodsUnitName" + index;
            errorCode2Msg.put(keyStr, goodErrorDto);
        } else {
            //判断物品计量单位的值是否正确
            Map<String, String> sysDictUnitBaseMap = sysDictService.findMapByCatalog(CommCodes.SYS_DICT_BIZ_UNIT_BASE);
            if (!CollectionUtils.isEmpty(sysDictUnitBaseMap)) {
                ordOrderBatchCargo.setGoodsUnit(null);
                sysDictUnitBaseMap.forEach((k, v) -> {
                    if (null != v && v.equals(goodsUnitName)) {
                        ordOrderBatchCargo.setGoodsUnit(k);
                        return;
                    }
                });
                if (StringUtils.isEmpty(ordOrderBatchCargo.getGoodsUnit())) {
                    OrdOrderBatchErrorDto goodErrorDto = new OrdOrderBatchErrorDto();
                    goodErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
                    //单位不正确
                    String keyStr = "goodsUnitName" + index;
                    errorCode2Msg.put(keyStr, goodErrorDto);
                }
            }
        }
        String goodsPrice = ordOrderBatchCargo.getGoodsPrice();
        if (StringUtils.isEmpty(goodsPrice)) {
            OrdOrderBatchErrorDto goodErrorDto = new OrdOrderBatchErrorDto();
            goodErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            String keyStr = "goodsPrice" + index;
            errorCode2Msg.put(keyStr, goodErrorDto);
        }
        String description = ordOrderBatchCargo.getDescription();
        if (StringUtils.isEmpty(description)) {
            OrdOrderBatchErrorDto goodErrorDto = new OrdOrderBatchErrorDto();
            goodErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            String keyStr = "description" + index;
            errorCode2Msg.put(keyStr, goodErrorDto);
        }
    }

    private boolean checkFieldValid(String regex, String fieldName) {
        if (null == fieldName) {
            return false;
        }
        if (null == regex) {
            return true;
        }
        Pattern pattern = Pattern.compile(regex);
        Matcher m = pattern.matcher(fieldName);
        if (!m.matches()) {
            return false;
        }
        return true;
    }

    //获取物品的校验规则
    private Map<String, Map<String, String>> getCheckRegex() {
        Map<String, String> regex2TipMap = Maps.newHashMap();
        Map<String, String> field2RegexMap = Maps.newHashMap();

        Map<String, Map<String, String>> field2RegexAndTipMap = Maps.newHashMap();
        field2RegexMap.put("goodsNameCn", "^[\\u4E00-\\u9FA5_\\w_\\-]{1,30}$");
        field2RegexMap.put("goodsNameEn", "^([\\w_\\-]+)+$");
        field2RegexMap.put("hsCode", "^\\d+$|^\\d+\\.\\d+$");
        field2RegexMap.put("goodsNumber", "^[1-9](\\d)*$");
        field2RegexMap.put("goodsUnitName", "^[\\u4E00-\\u9FA5A-Za-z0-9]{1,30}$");
        field2RegexMap.put("goodsPrice", "^(?!0+(?:\\.0+)?$)(?:[1-9]\\d*|0)(?:\\.\\d{1,3})?$");
        field2RegexMap.put("description", "^[\\u4E00-\\u9FA5_\\w_\\-]{1,30}$");
        field2RegexMap.put("EMAIL", "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$");
        field2RegexMap.put("PHONE", "^([\\d_\\-\\+]+)+$");
        field2RegexMap.put("IMOCODE", "^([\\w]+)+$");
        field2RegexMap.put("cusWeight", "^(?!0+(?:\\.0+)?$)(?:[1-9]\\d*|0)(?:\\.\\d{1,3})?$");
        field2RegexMap.put("NAME", "^([\\w\\u4E00-\\u9FA5_\\-\\s]+)+$");
        //正则表达式对应的提示信息

        regex2TipMap.put("^[\\u4E00-\\u9FA5_\\w_\\-]{1,30}$", "请输入中英文、数字和符号-、_");
        regex2TipMap.put("^([\\w_\\-]+)+$", "请输入大小写字母、数字和符号-、_");
        //hscode
        regex2TipMap.put("^\\d+$|^\\d+\\.\\d+$", "请输入小数点和数字，不包含小数点可以输入10位数字，包含小数点可以输入11位");
        regex2TipMap.put("^[1-9](\\d)*$", "请输入正整数");
        regex2TipMap.put("^[\\u4E00-\\u9FA5A-Za-z0-9]{1,30}$", "计量单位不合法");
        regex2TipMap.put("^^(?!0+(?:\\.0+)?$)(?:[1-9]\\d*|0)(?:\\.\\d{1,3})?$", "请输入数字和小数点，可精确到小数点后3位，且应大于0");
        regex2TipMap.put("^[\\u4E00-\\u9FA5_\\w_\\-]{1,30}$", "请输入中英文、数字和符号-、_");
        regex2TipMap.put("^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$", "请输入有效的邮箱地址");
        regex2TipMap.put("^([\\d_\\-\\+]+)+$", "请输入数字或符号“-”、“_”、“+”");
        regex2TipMap.put("^([\\w]+)+$", "请输入数字或字母");
        regex2TipMap.put("^(?!0+(?:\\.0+)?$)(?:[1-9]\\d*|0)(?:\\.\\d{1,3})?$", "请输入数字和小数点，可精确到小数点后3位，且应大于0");
        regex2TipMap.put("^([\\w\\u4E00-\\u9FA5_\\-\\s]+)+$", "请输入中英文、数字、空格和符号“-”、“_”");
        field2RegexAndTipMap.put("regex", field2RegexMap);
        field2RegexAndTipMap.put("tip", regex2TipMap);
        return field2RegexAndTipMap;
    }

    //将校验正确的发件人地址信息重写回orderBatch
    private void setFromAddressInfo(OrderAddressModel orderAddressModel, OrdOrderBatch ordOrderBatch, String addressType) {
        ordOrderBatch.setFromDetailCode(this.setAddressDetailCode(orderAddressModel, addressType));

    }

    //将校验正确的收件人地址信息重写回orderBatch
    private void setToAddressInfo(OrderAddressModel orderAddressModel, OrdOrderBatch ordOrderBatch, String addressType) {
        ordOrderBatch.setToDetailCode(this.setAddressDetailCode(orderAddressModel, addressType));

    }

    //将校验正确的揽收地址信息重写回orderBatch
    private void setFetchAddressInfo(OrderAddressModel orderAddressModel, OrdOrderBatch ordOrderBatch, String addressType) {
        ordOrderBatch.setFetchDetailCode(this.setAddressDetailCode(orderAddressModel, addressType));

    }

    private String setAddressDetailCode(OrderAddressModel orderAddressModel, String addressType) {
        //set地址信息Code
        StringBuilder sb = new StringBuilder();
        sb.append("cusTransportType:" + addressType);
        if (null != orderAddressModel.getCountryCode()) {
            sb.append("|" + "countryCode:" + orderAddressModel.getCountryCode());
        }
        if (null != orderAddressModel.getProvinceId()) {
            sb.append("|" + "provinceId:" + orderAddressModel.getProvinceId());
        }
        if (null != orderAddressModel.getCityId()) {
            sb.append("|" + "cityId:" + orderAddressModel.getCityId());
        }
        if (null != orderAddressModel.getDistrictId()) {
            sb.append("|" + "districtId:" + orderAddressModel.getDistrictId());
        }
        if (null != orderAddressModel.getStreetId()) {
            sb.append("|" + "streetId:" + orderAddressModel.getStreetId());
        }
        if (null != orderAddressModel.getTransportId()) {
            sb.append("|" + "transportId:" + orderAddressModel.getTransportId());
        }
        return sb.toString();
    }

    /**
     * 校验Excel数据地址信息
     *
     * @param orderBatch
     * @return
     */
    private boolean checkExcelAddressInfo(OrdOrderBatch orderBatch, String transportType, boolean isSudi, boolean isFetch, String productUid, Map<String, OrdOrderBatchErrorDto> errorCode2Msg) {
        OrdOrderBatchErrorDto addressErrorDto = new OrdOrderBatchErrorDto();
        OrderAddressModel orderFromAddressModel = this.getAdderssFromBatch(orderBatch, CommCodes.ADDRESS_TYPE_FROM);
        orderFromAddressModel.setTransportType(Integer.parseInt(transportType));
        OrderAddressModel orderToAddressModel = this.getAdderssFromBatch(orderBatch, CommCodes.ADDRESS_TYPE_TO);
        orderToAddressModel.setTransportType(Integer.parseInt(transportType));
        boolean flagVanFromAddress = checkVanAddressInfo(orderFromAddressModel, isSudi);
        boolean fromAddress = false;
        if (flagVanFromAddress) {
            addressErrorDto.setErrorCode(ErrorCodes.ERROR_COMMON.getCode());
            addressErrorDto.setMessage(CommCodes.FROM_ADDRESS_NOT_IN_SERVICE_SCOPE_CUSTOMER);
            errorCode2Msg.put("fromAddress", addressErrorDto);
        } else {
            fromAddress = this.checkAddressInfo(orderFromAddressModel, isSudi, transportType);
            //fromAddress = orderCommService.checkAddress(orderFromAddressModel);
            //处理正确的地址名称
            processNameOfAddress(orderBatch, orderFromAddressModel, CommCodes.ADDRESS_TYPE_FROM);
            orderBatch.setFromCountry(orderFromAddressModel.getCountryName());
            if (!fromAddress) {
                addressErrorDto.setErrorCode(ErrorCodes.ERROR_COMMON.getCode());
                addressErrorDto.setMessage(CommCodes.FROM_ADDRESS_NOT_IN_SERVICE_SCOPE_CUSTOMER);
                errorCode2Msg.put("fromAddress", addressErrorDto);
                return false;
            }
            //校验 发件地址服务范围
            List<ProductAddressDto> productAddressDtoList = productService.getProductAddress(productUid, CommCodes.PRODUCT_SERVICE_REGION_START);
            ProductAddressDto productAddressDto = new ProductAddressDto();
            this.changeProductVO(orderFromAddressModel, productAddressDto, CommCodes.ADDRESS_TYPE_FROM);
            boolean isOk = productService.checkProductAddress(productAddressDtoList, productAddressDto);
            if (!isOk) {
                addressErrorDto.setErrorCode(ErrorCodes.ERROR_COMMON.getCode());
                addressErrorDto.setMessage(CommCodes.FROM_ADDRESS_NOT_IN_SERVICE_SCOPE_CUSTOMER);
                errorCode2Msg.put("fromAddress", addressErrorDto);
                return false;
            }
            //设置发件人Detail和DetailCode
            setFromAddressInfo(orderFromAddressModel, orderBatch, transportType);
            orderBatch.setFromDetail(getFromDetail(orderBatch, TransportTypeEnum.valueOfEnum(transportType).getName()));
        }
        boolean flagVanToAddress = checkVanAddressInfo(orderToAddressModel, isSudi);
        boolean toAddress = false;
        if (flagVanToAddress) {
            addressErrorDto.setErrorCode(ErrorCodes.ERROR_COMMON.getCode());
            addressErrorDto.setMessage(CommCodes.TO_ADDRESS_NOT_IN_SERVICE_SCOPE_CUSTOMER);
            errorCode2Msg.put("toAddress", addressErrorDto);
            return false;
        } else {
            toAddress = this.checkAddressInfo(orderToAddressModel, isSudi, transportType);
            //处理正确的地址名称
            processNameOfAddress(orderBatch, orderToAddressModel, CommCodes.ADDRESS_TYPE_TO);
            orderBatch.setToCountry(orderToAddressModel.getCountryName());
            if (!toAddress) {
                addressErrorDto.setErrorCode(ErrorCodes.ERROR_COMMON.getCode());
                addressErrorDto.setMessage(CommCodes.TO_ADDRESS_NOT_IN_SERVICE_SCOPE_CUSTOMER);
                errorCode2Msg.put("toAddress", addressErrorDto);
                return false;
            }
            //校验 收件地址服务范围
            List<ProductAddressDto> productAddressDtoList = productService.getProductAddress(productUid, CommCodes.PRODUCT_SERVICE_REGION_END);
            ProductAddressDto productAddressDto = new ProductAddressDto();
            this.changeProductVO(orderToAddressModel, productAddressDto, CommCodes.ADDRESS_TYPE_TO);
            boolean isOk = productService.checkProductAddress(productAddressDtoList, productAddressDto);
            if (!isOk) {
                addressErrorDto.setErrorCode(ErrorCodes.ERROR_COMMON.getCode());
                addressErrorDto.setMessage(CommCodes.TO_ADDRESS_NOT_IN_SERVICE_SCOPE_CUSTOMER);
                errorCode2Msg.put("toAddress", addressErrorDto);
                return false;
            }
            //设置收件人Detail和DetailCode
            setToAddressInfo(orderToAddressModel, orderBatch, transportType);
            orderBatch.setToDetail(getToDetail(orderBatch, TransportTypeEnum.valueOfEnum(transportType).getName()));
        }
        if (isFetch) {
            OrderAddressModel orderFetchAddressModel = this.getAdderssFromBatch(orderBatch, CommCodes.ADDRESS_TYPE_FETCH);
            orderFetchAddressModel.setTransportType(CommCodes.TRANSPORT_LAND);
            boolean flagVanFetchAddress = checkVanAddressInfo(orderFetchAddressModel, true);
            boolean fetchAddress = false;
            if (flagVanFetchAddress) {
                addressErrorDto.setErrorCode(ErrorCodes.ERROR_COMMON.getCode());
                addressErrorDto.setMessage(CommCodes.FETCH_ADDRESS_NOT_IN_SERVICE_SCOPE);
                errorCode2Msg.put("fetchAddress", addressErrorDto);
                return false;
            } else {
                fetchAddress = this.checkAddressInfo(orderFetchAddressModel, true, transportType);
                //处理正确的地址名称
                processNameOfAddress(orderBatch, orderFetchAddressModel, CommCodes.ADDRESS_TYPE_FETCH);
                orderBatch.setFetchCountry(orderFetchAddressModel.getCountryName());
                //校验 提货地址服务范围
                if (!fetchAddress) {
                    addressErrorDto.setErrorCode(ErrorCodes.ERROR_COMMON.getCode());
                    addressErrorDto.setMessage(CommCodes.FETCH_ADDRESS_NOT_IN_SERVICE_SCOPE);
                    errorCode2Msg.put("fetchAddress", addressErrorDto);
                    return false;
                }
                List<ProductAddressDto> productAddressDtoList = productService.getProductAddress(productUid, CommCodes.PRODUCT_SERVICE_REGION_PICKUP);
                ProductAddressDto productAddressDto = new ProductAddressDto();
                this.changeProductVO(orderFetchAddressModel, productAddressDto, CommCodes.ADDRESS_TYPE_FETCH);
                boolean isOk = productService.checkProductAddress(productAddressDtoList, productAddressDto);

                if (!isOk) {
                    addressErrorDto.setErrorCode(ErrorCodes.ERROR_COMMON.getCode());
                    addressErrorDto.setMessage(CommCodes.FETCH_ADDRESS_NOT_IN_SERVICE_SCOPE);
                    errorCode2Msg.put("fetchAddress", addressErrorDto);
                    return false;
                }
                setFetchAddressInfo(orderFetchAddressModel, orderBatch, String.valueOf(CommCodes.TRANSPORT_LAND));
                orderBatch.setFetchDetail(String.valueOf(CommCodes.TRANSPORT_LAND) + getFetchDetail(orderBatch));
            }
        }
        return true;
    }

    /**
     * 校验通过之后，处理正确的地址名称
     *
     * @param addressModel
     * @param addressType
     */
    private void processNameOfAddress(OrdOrderBatch orderBatch, OrderAddressModel addressModel, String addressType) {

        switch (addressType) {
            case CommCodes.ADDRESS_TYPE_FROM:
                if (!StringUtils.isEmpty(addressModel.getCountryCode())) {
                    orderBatch.setFromCountry(addressModel.getCountryCode());
                }
                if (!StringUtils.isEmpty(addressModel.getProvinceName())) {
                    orderBatch.setFromProvince(addressModel.getProvinceName());
                }
                if (!StringUtils.isEmpty(addressModel.getCityName())) {
                    orderBatch.setFromCity(addressModel.getCityName());
                }
                if (!StringUtils.isEmpty(addressModel.getDistrictName())) {
                    orderBatch.setFromDistrict(addressModel.getDistrictName());
                }
                if (!StringUtils.isEmpty(addressModel.getStreetName())) {
                    orderBatch.setFromStreet(addressModel.getStreetName());
                }
                break;
            case CommCodes.ADDRESS_TYPE_TO:
                if (!StringUtils.isEmpty(addressModel.getCountryCode())) {
                    orderBatch.setToCountry(addressModel.getCountryCode());
                }
                if (!StringUtils.isEmpty(addressModel.getProvinceName())) {
                    orderBatch.setToProvince(addressModel.getProvinceName());
                }
                if (!StringUtils.isEmpty(addressModel.getCityName())) {
                    orderBatch.setToCity(addressModel.getCityName());
                }
                if (!StringUtils.isEmpty(addressModel.getDistrictName())) {
                    orderBatch.setToDistrict(addressModel.getDistrictName());
                }
                if (!StringUtils.isEmpty(addressModel.getStreetName())) {
                    orderBatch.setToStreet(addressModel.getStreetName());
                }
                break;
            case CommCodes.ADDRESS_TYPE_FETCH:
                if (!StringUtils.isEmpty(addressModel.getCountryCode())) {
                    orderBatch.setFetchCountry(addressModel.getCountryCode());
                }
                if (!StringUtils.isEmpty(addressModel.getProvinceName())) {
                    orderBatch.setFetchProvince(addressModel.getProvinceName());
                }
                if (!StringUtils.isEmpty(addressModel.getCityName())) {
                    orderBatch.setFetchCity(addressModel.getCityName());
                }
                if (!StringUtils.isEmpty(addressModel.getDistrictName())) {
                    orderBatch.setFetchDistrict(addressModel.getDistrictName());
                }
                if (!StringUtils.isEmpty(addressModel.getStreetName())) {
                    orderBatch.setFetchStreet(addressModel.getStreetName());
                }
                break;
            default:
                break;

        }

    }

    private void setRightToAddressInfo(OrdOrderBatch orderBatch, OrderAddressModel orderToAddressModel) {
        orderBatch.setToCountry(orderToAddressModel.getCountryName());
        orderBatch.setToProvince(orderToAddressModel.getProvinceName());
        orderBatch.setToCity(orderToAddressModel.getCityName());
        orderBatch.setToDistrict(orderToAddressModel.getDistrictName());
        orderBatch.setToStreet(orderToAddressModel.getStreetName());
    }

    private void setRightFromAddressInfo(OrdOrderBatch orderBatch, OrderAddressModel orderFromAddressModel) {
        orderBatch.setFromCountry(orderFromAddressModel.getCountryName());
        orderBatch.setFromProvince(orderFromAddressModel.getProvinceName());
        orderBatch.setFromCity(orderFromAddressModel.getCityName());
        orderBatch.setFromDistrict(orderFromAddressModel.getDistrictName());
        orderBatch.setFromStreet(orderFromAddressModel.getStreetName());
    }

    private void setRightFetchAddressInfo(OrdOrderBatch orderBatch, OrderAddressModel orderFetchAddressModel) {
        orderBatch.setFetchCountry(orderFetchAddressModel.getCountryName());
        orderBatch.setFetchProvince(orderFetchAddressModel.getProvinceName());
        orderBatch.setFetchCity(orderFetchAddressModel.getCityName());
        orderBatch.setFetchDistrict(orderFetchAddressModel.getDistrictName());
        orderBatch.setFetchStreet(orderFetchAddressModel.getStreetName());
    }

    private void checkExcelAddressInfoForDetail(OrdOrderBatch orderBatch, String transportType, boolean isSudi, boolean isFetch, String productUid, Map<String, OrdOrderBatchErrorDto> errorCode2Msg) {
        OrdOrderBatchErrorDto addressErrorDto;
        OrderAddressModel orderFromAddressModel = this.getAdderssFromBatch(orderBatch, CommCodes.ADDRESS_TYPE_FROM);
        OrderAddressModel orderToAddressModel = this.getAdderssFromBatch(orderBatch, CommCodes.ADDRESS_TYPE_TO);
        boolean flagVanFromAddress = checkVanAddressInfo(orderFromAddressModel, isSudi);
        boolean fromAddress = false;
        if (flagVanFromAddress) {
            addressErrorDto = new OrdOrderBatchErrorDto();
            addressErrorDto.setErrorCode(CommonErrorCodes.ERROR_ARGUMENT_ILLEGAL.getCode());
            addressErrorDto.setMessage(CommCodes.FROM_ADDRESS_NOT_IN_SERVICE_SCOPE_CUSTOMER);
            errorCode2Msg.put("fromAddress", addressErrorDto);
        } else {
            fromAddress = this.checkAddressInfo(orderFromAddressModel, isSudi, transportType);
            if (org.apache.commons.lang3.StringUtils.isNotBlank(orderFromAddressModel.getCountryName())) {
                orderBatch.setFromCountry(orderFromAddressModel.getCountryName());
            }
            if (fromAddress) {
                //校验 发件地址服务范围
                List<ProductAddressDto> productAddressDtoList = productService.getProductAddress(productUid, CommCodes.PRODUCT_SERVICE_REGION_START);
                ProductAddressDto productAddressDto = new ProductAddressDto();
                this.changeProductVO(orderFromAddressModel, productAddressDto, CommCodes.ADDRESS_TYPE_FROM);
                boolean isOk = productService.checkProductAddress(productAddressDtoList, productAddressDto);
                if (!isOk) {
                    addressErrorDto = new OrdOrderBatchErrorDto();
                    addressErrorDto.setErrorCode(ErrorCodes.ERROR_COMMON.getCode());
                    addressErrorDto.setMessage(CommCodes.FROM_ADDRESS_NOT_IN_SERVICE_SCOPE_CUSTOMER);
                    errorCode2Msg.put("fromAddress", addressErrorDto);
                } else {
                    setRightFromAddressInfo(orderBatch, orderFromAddressModel);
                }
                //设置发件人Detail和DetailCode
                setFromAddressInfo(orderFromAddressModel, orderBatch, transportType);
                orderBatch.setFromDetail(getFromDetail(orderBatch, TransportTypeEnum.valueOfEnum(transportType).getName()));
            } else {
                addressErrorDto = new OrdOrderBatchErrorDto();
                addressErrorDto.setErrorCode(ErrorCodes.ERROR_COMMON.getCode());
                addressErrorDto.setMessage(CommCodes.FROM_ADDRESS_NOT_IN_SERVICE_SCOPE_CUSTOMER);
                errorCode2Msg.put("fromAddress", addressErrorDto);
            }
        }
        if (null == errorCode2Msg.get(FROM_ADDRESS) && StringUtils.isEmpty(orderBatch.getFromDetailCode())) {
            orderBatch.setFromDetailCode(setAddressDetailCode(orderFromAddressModel, transportType));
        }
        boolean flagVanToAddress = checkVanAddressInfo(orderToAddressModel, isSudi);
        boolean toAddress = false;
        if (flagVanToAddress) {
            addressErrorDto = new OrdOrderBatchErrorDto();
            addressErrorDto.setErrorCode(ErrorCodes.ERROR_COMMON.getCode());
            addressErrorDto.setMessage(CommCodes.TO_ADDRESS_NOT_IN_SERVICE_SCOPE_CUSTOMER);
            errorCode2Msg.put("toAddress", addressErrorDto);
        } else {
            toAddress = this.checkAddressInfo(orderToAddressModel, isSudi, transportType);
            if (org.apache.commons.lang3.StringUtils.isNotBlank(orderToAddressModel.getCountryName())) {
                orderBatch.setToCountry(orderToAddressModel.getCountryName());
            }
            if (toAddress) {
                //校验 收件地址服务范围
                List<ProductAddressDto> productAddressDtoList = productService.getProductAddress(productUid, CommCodes.PRODUCT_SERVICE_REGION_END);
                ProductAddressDto productAddressDto = new ProductAddressDto();
                this.changeProductVO(orderToAddressModel, productAddressDto, CommCodes.ADDRESS_TYPE_TO);
                boolean isOk = productService.checkProductAddress(productAddressDtoList, productAddressDto);
                if (!isOk) {
                    addressErrorDto = new OrdOrderBatchErrorDto();
                    addressErrorDto.setErrorCode(ErrorCodes.ERROR_COMMON.getCode());
                    addressErrorDto.setMessage(CommCodes.TO_ADDRESS_NOT_IN_SERVICE_SCOPE_CUSTOMER);
                    errorCode2Msg.put("toAddress", addressErrorDto);
                } else {
                    setRightToAddressInfo(orderBatch, orderToAddressModel);
                }
                //设置收件人Detail和DetailCode
                setToAddressInfo(orderToAddressModel, orderBatch, transportType);
                orderBatch.setToDetail(getToDetail(orderBatch, TransportTypeEnum.valueOfEnum(transportType).getName()));
            } else {
                addressErrorDto = new OrdOrderBatchErrorDto();
                addressErrorDto.setErrorCode(ErrorCodes.ERROR_COMMON.getCode());
                addressErrorDto.setMessage(CommCodes.TO_ADDRESS_NOT_IN_SERVICE_SCOPE_CUSTOMER);
                errorCode2Msg.put("toAddress", addressErrorDto);
            }
        }
        if (null == errorCode2Msg.get(TO_ADDRESS) && StringUtils.isEmpty(orderBatch.getToDetailCode())) {
            orderBatch.setToDetailCode(setAddressDetailCode(orderToAddressModel, transportType));
        }
        if (isFetch) {
            OrderAddressModel orderFetchAddressModel = this.getAdderssFromBatch(orderBatch, CommCodes.ADDRESS_TYPE_FETCH);
            boolean flagVanFetchAddress = checkVanAddressInfo(orderFetchAddressModel, true);
            boolean fetchAddress = false;
            if (flagVanFetchAddress) {
                addressErrorDto = new OrdOrderBatchErrorDto();
                addressErrorDto.setErrorCode(ErrorCodes.ERROR_COMMON.getCode());
                addressErrorDto.setMessage(CommCodes.FETCH_ADDRESS_NOT_IN_SERVICE_SCOPE);
                errorCode2Msg.put("fetchAddress", addressErrorDto);
            } else {
                fetchAddress = this.checkAddressInfo(orderFetchAddressModel, true, transportType);
                if (org.apache.commons.lang3.StringUtils.isNotBlank(orderFetchAddressModel.getCountryName())) {
                    orderBatch.setFetchCountry(orderFetchAddressModel.getCountryName());
                }
                //校验 提货地址服务范围
                if (fetchAddress) {
                    List<ProductAddressDto> productAddressDtoList = productService.getProductAddress(productUid, CommCodes.PRODUCT_SERVICE_REGION_PICKUP);
                    ProductAddressDto productAddressDto = new ProductAddressDto();
                    this.changeProductVO(orderFetchAddressModel, productAddressDto, CommCodes.ADDRESS_TYPE_FETCH);
                    boolean isOk = productService.checkProductAddress(productAddressDtoList, productAddressDto);
                    if (!isOk) {
                        addressErrorDto = new OrdOrderBatchErrorDto();
                        addressErrorDto.setErrorCode(ErrorCodes.ERROR_COMMON.getCode());
                        addressErrorDto.setMessage(CommCodes.FETCH_ADDRESS_NOT_IN_SERVICE_SCOPE);
                        errorCode2Msg.put("fetchAddress", addressErrorDto);
                    } else {
                        setRightFetchAddressInfo(orderBatch, orderFetchAddressModel);
                    }
                    //设置揽收人Detail和DetailCode
                    setFetchAddressInfo(orderFetchAddressModel, orderBatch, String.valueOf(CommCodes.TRANSPORT_LAND));
                    orderBatch.setFetchDetail(String.valueOf(CommCodes.TRANSPORT_LAND) + getFetchDetail(orderBatch));
                } else {
                    addressErrorDto = new OrdOrderBatchErrorDto();
                    addressErrorDto.setErrorCode(ErrorCodes.ERROR_COMMON.getCode());
                    addressErrorDto.setMessage(CommCodes.FETCH_ADDRESS_NOT_IN_SERVICE_SCOPE);
                    errorCode2Msg.put("fetchAddress", addressErrorDto);
                }
            }
            if (null == errorCode2Msg.get(FETCH_ADDRESS) && StringUtils.isEmpty(orderBatch.getFetchDetailCode())) {
                orderBatch.setFetchDetailCode(setAddressDetailCode(orderFetchAddressModel, transportType));
            }
        }
    }

    private void changeProductVO(OrderAddressModel orderAddressModel, ProductAddressDto productAddressDto, String addressFrom) {
        productAddressDto.setCountry(orderAddressModel.getCountryCode());
        if (LanguageCode.CN_UPPER.equals(orderAddressModel.getCountryCode())) {
            productAddressDto.setProvince(orderAddressModel.getProvinceId());
        }
        productAddressDto.setArea(orderAddressModel.getDistrictId());
        productAddressDto.setCity(orderAddressModel.getCityId());
        productAddressDto.setStreet(orderAddressModel.getStreetId());
        productAddressDto.setTransportType(orderAddressModel.getTransportType());
        productAddressDto.setTransportId(orderAddressModel.getTransportId());

        if (CommCodes.ADDRESS_TYPE_FROM.equals(addressFrom)) {
            productAddressDto.setAddressType(CommCodes.PRODUCT_SERVICE_REGION_START);
        } else if (CommCodes.ADDRESS_TYPE_TO.equals(addressFrom)) {
            productAddressDto.setAddressType(CommCodes.PRODUCT_SERVICE_REGION_END);
        } else if (CommCodes.ADDRESS_TYPE_FETCH.equals(addressFrom)) {
            productAddressDto.setAddressType(CommCodes.PRODUCT_SERVICE_REGION_PICKUP);
        }


    }

    private void setAddressModelAirPortOrPort(Map<String, Object> type2Object, String transportType, OrderAddressModel orderAddressModel) {
        if (!CollectionUtils.isEmpty(type2Object)) {
            Object objectFrom = type2Object.get(transportType);
            if (objectFrom instanceof Airport) {
                Airport airPort = (Airport) objectFrom;
                if (LanguageCode.CN_UPPER.equalsIgnoreCase(orderAddressModel.getCountryCode())) {
                    List<AreaDto> provices = areaManager.findByAreaId(orderAddressModel.getCountryCode(), String.valueOf(airPort.getCityId()));
                    if (!CollectionUtils.isEmpty(provices) && provices.size() == 1) {
                        orderAddressModel.setProvinceId(provices.get(0).getParentId());
                    }
                }
                orderAddressModel.setTransportId(airPort.getId());
                orderAddressModel.setCityId(airPort.getCityId());
            }

            if (objectFrom instanceof Port) {
                Port port = (Port) objectFrom;
                List<AreaDto> portDtos = areaManager.findByAreaId(orderAddressModel.getCountryCode(), String.valueOf(port.getCityId()));
                if (!CollectionUtils.isEmpty(portDtos) && portDtos.size() == 1) {
                    orderAddressModel.setProvinceId(portDtos.get(0).getParentId());
                }
                orderAddressModel.setTransportId(port.getId());
                orderAddressModel.setCityId(port.getCityId());
            }
        }
    }

    /**
     * 校验地址信息中的必填信息
     *
     * @param orderAddressModel
     * @param isSudi
     * @return
     */
    private boolean checkVanAddressInfo(OrderAddressModel orderAddressModel, boolean isSudi) {
        boolean flagVan = false;
        String countryName = orderAddressModel.getCountryName();
        String districtName = orderAddressModel.getDistrictName();
        String address = orderAddressModel.getAddress();
        if (StringUtils.isEmpty(countryName)) {
            flagVan = true;
        }
        if (isSudi) {
            if (StringUtils.isEmpty(address)) {
                flagVan = true;
            }
        } else {
            if (StringUtils.isEmpty(districtName)) {
                flagVan = true;
            }
        }

        return flagVan;
    }

    /**
     * 校验四级地址信息是否为空
     *
     * @param orderAddressModel
     * @return
     */
    private boolean checkCommonAddress(OrderAddressModel orderAddressModel) {
        boolean flagVan = false;
        String cityName = orderAddressModel.getCityName();
        String districtName = orderAddressModel.getDistrictName();
        String streetName = orderAddressModel.getStreetName();
        if (StringUtils.isEmpty(cityName)) {
            flagVan = true;
        }
        if (StringUtils.isEmpty(districtName)) {
            flagVan = true;
        }
        if (StringUtils.isEmpty(streetName)) {
            flagVan = true;
        }

        return flagVan;
    }

    /**
     * 设置国家二字码
     */
    private void setExcelOrderCountryCode(List<OrdOrderBatch> ordOrderBatchList) {
        for (OrdOrderBatch ordOrderBatch : ordOrderBatchList) {
            String fromCountry = ordOrderBatch.getFromCountry();
            String toCountry = ordOrderBatch.getToCountry();
            String fetchCountry = ordOrderBatch.getFetchCountry();
            if (org.apache.commons.lang3.StringUtils.isNotBlank(fromCountry)) {
                List<CountryModel> fromCountryModels = areaService.getCountrysByNameOrCode(fromCountry);
                if (!CollectionUtils.isEmpty(fromCountryModels)) {
                    CountryModel fromCountryInfo = fromCountryModels.get(0);
                    ordOrderBatch.setFromCountry(fromCountryInfo.getCode());
                }
            }
            if (org.apache.commons.lang3.StringUtils.isNotBlank(toCountry)) {
                List<CountryModel> toCountryModels = areaService.getCountrysByNameOrCode(toCountry);
                if (!CollectionUtils.isEmpty(toCountryModels)) {
                    CountryModel toCountryInfo = toCountryModels.get(0);
                    ordOrderBatch.setToCountry(toCountryInfo.getCode());
                }
            }
            if (org.apache.commons.lang3.StringUtils.isNotBlank(fetchCountry)) {
                List<CountryModel> fetchCountryModels = areaService.getCountrysByNameOrCode(fetchCountry);
                if (!CollectionUtils.isEmpty(fetchCountryModels)) {
                    CountryModel fetchCountryInfo = fetchCountryModels.get(0);
                    ordOrderBatch.setFetchCountry(fetchCountryInfo.getCode());
                }
            }
        }
    }

    private boolean checkVoidAddressInfo(String addressInfo) {
        if (StringUtils.isEmpty(addressInfo)) {
            return false;
        }
        return true;
    }

    /**
     * 校验地址信息
     *
     * @param orderAddressModel
     * @return
     */
    private boolean checkAddressInfo(OrderAddressModel orderAddressModel, boolean isSudi, String transportType) {
        //校验国家
        String countryName = orderAddressModel.getCountryName();
        //校验国家是否为空
        boolean checkVoidResult = checkVoidAddressInfo(countryName);
        if (!checkVoidResult) {
            return false;
        }
        String changeCountryName = changeCountry(countryName);
        List<CountryModel> countryModels = areaService.getCountrysByNameOrCode(countryName);
        if (countryModels.size() == 1) {
            //设置国家编码和名称
            orderAddressModel.setCountryCode(countryModels.get(0).getCode());
            orderAddressModel.setCountryName(countryModels.get(0).getName());
            if (LanguageCode.CHINA.equals(countryName) || LanguageCode.CN_UPPER.equals(changeCountryName)) {
                if (isSudi) {
                    String provinceName = orderAddressModel.getProvinceName();
                    //校验省份是否为空
                    boolean checkProvinceResult = checkVoidAddressInfo(provinceName);
                    if (!checkProvinceResult) {
                        return false;
                    }
                    //校验省份
                    if (provinceName.lastIndexOf(RegionConstants.AreaType.PROVINCE) > 0) {
                        provinceName = provinceName.substring(0, provinceName.length() - 1);
                    }
                    ResultDto resultProvice = areaManager.findByParentId(LanguageCode.CN_UPPER, "0", provinceName, 0, 100);
                    List<AreaDto> areaProviceDtos = (List<AreaDto>) resultProvice.getData();
                    if (!CollectionUtils.isEmpty(areaProviceDtos) && areaProviceDtos.size() == 1) {
                        String cityName = orderAddressModel.getCityName();
                        //校验城市是否为空
                        boolean checkCityResult = checkVoidAddressInfo(cityName);
                        if (!checkCityResult) {
                            return false;
                        }
                        //校验市
                        if (cityName.lastIndexOf(RegionConstants.AreaType.CITY) > 0) {
                            cityName = cityName.substring(0, cityName.length() - 1);
                        }
                        AreaDto areaProviceDto = areaProviceDtos.get(0);
                        //设置省份ID和名称
                        orderAddressModel.setProvinceId(areaProviceDto.getId());
                        orderAddressModel.setProvinceName(areaProviceDto.getName());
                        ResultDto resultCity = areaManager.findByParentId(LanguageCode.CN_UPPER, areaProviceDto.getId(), cityName, 0, 100);
                        List<AreaDto> areaCityDtos = (List<AreaDto>) resultCity.getData();
                        if (!CollectionUtils.isEmpty(areaCityDtos) && areaCityDtos.size() == 1) {
                            AreaDto areaCityDto = areaCityDtos.get(0);
                            //设置城市ID
                            orderAddressModel.setCityId(areaCityDto.getId());
                            orderAddressModel.setCityName(areaCityDto.getName());
                            //获取数据库中该城市下的区县，如果有，则继续校验，如果没有，则不再校验
                            ResultDto resultDistrict = areaManager.findByParentId(LanguageCode.CN_UPPER, areaCityDto.getId(), null, 0, 100);
                            List<AreaDto> areaDistrictDtos = (List<AreaDto>) resultDistrict.getData();
                            if (!CollectionUtils.isEmpty(areaDistrictDtos)) {
                                //校验区、县
                                String districtName = orderAddressModel.getDistrictName();
                                //校验区县是否为空
                                boolean checkDistrictResult = checkVoidAddressInfo(districtName);
                                if (!checkDistrictResult) {
                                    return false;
                                }
                                //精确匹配县，区。
                                AreaDto areaDistrictDto = this.getUniqueTownInfo(areaDistrictDtos, districtName);
                                if (!ObjectUtils.isEmpty(areaDistrictDto)) {
                                    //设置区、县ID
                                    orderAddressModel.setDistrictId(areaDistrictDto.getId());
                                    orderAddressModel.setDistrictName(areaDistrictDto.getName());
                                    //获取数据库中该区县下的街道，如果有，则继续校验，如果没有，则不再校验
                                    ResultDto resultStreet = areaManager.findByParentId(LanguageCode.CN_UPPER, areaDistrictDto.getId(), null, 0, 100);
                                    List<AreaDto> areaStreetDtos = (List<AreaDto>) resultStreet.getData();
                                    if (!CollectionUtils.isEmpty(areaStreetDtos)) {
                                        //校验街道
                                        String streetName = orderAddressModel.getStreetName();
                                        //校验街道是否为空
                                        boolean checkStreetResult = checkVoidAddressInfo(streetName);
                                        if (!checkStreetResult) {
                                            return false;
                                        }
                                        //精确匹配街道。
                                        AreaDto areaStreettDto = this.getUniqueTownInfo(areaStreetDtos, streetName);
                                        if (!ObjectUtils.isEmpty(areaStreettDto)) {
                                            //设置街道ID
                                            orderAddressModel.setStreetId(areaStreettDto.getId());
                                            orderAddressModel.setStreetName(areaStreettDto.getName());
                                        } else {
                                            return false;
                                        }
                                    } else {
                                        orderAddressModel.setStreetName(null);
                                    }

                                } else {
                                    return false;
                                }
                            } else {
                                orderAddressModel.setDistrictName(null);
                                orderAddressModel.setStreetName(null);
                            }
                        } else {
                            return false;
                        }
                    } else {
                        return false;
                    }
                } else {
                    //若不是速递，校验发货地址的港口或机场信息
                    boolean result = this.checkPortOrAirPort(orderAddressModel, transportType);
                    if (!result) {
                        return false;
                    }
                }
            } else if (!LanguageCode.CHINA.equals(countryName) && !LanguageCode.CN_UPPER.equals(changeCountryName)) {
                //国外地址
                String cityName = orderAddressModel.getCityName();
                ResultDto resultCity = areaManager.findByParentId(countryModels.get(0).getCode(), countryModels.get(0).getCode(), cityName, 0, 100);
                List<AreaDto> areaDtos = (List<AreaDto>) resultCity.getData();
                if (!isSudi) {
                    //若不是速递，校验发货地址的港口或机场信息
                    boolean result = this.checkPortOrAirPort(orderAddressModel, transportType);
                    if (!result) {
                        return false;
                    }
                } else {
                    //国外城市需要精确匹配，modify by xiaoyanhong
                    if (!CollectionUtils.isEmpty(areaDtos)) {
                        AreaDto areaCityDto = getForeignCity(areaDtos, cityName);
                        if (null != areaCityDto && null != areaCityDto.getId()) {
                            orderAddressModel.setCityId(areaCityDto.getId());
                            orderAddressModel.setCityName(areaCityDto.getName());
                        } else {
                            return false;
                        }
                    } else {
                        return false;
                    }
                }
            } else {
                return false;
            }
        } else {
            return false;
        }
        return true;
    }

    //精确匹配区/县
    //modify by xiaoyanhong  2017-12-18 不要精确匹配
    private AreaDto getUniqueTownInfo(List<AreaDto> areaDistrictDtos, String orignalDistrictName) {
        AreaDto areaDto = null;
        if (!StringUtils.isEmpty(orignalDistrictName)) {
            if (areaDistrictDtos.size() == 1) {
                areaDto = areaDistrictDtos.get(0);
            } else {
                for (AreaDto areaTownDto : areaDistrictDtos) {
                    if (areaTownDto.getName().startsWith(orignalDistrictName)) {
                        areaDto = areaTownDto;
                        break;
                    }
                }
            }
        }
        return areaDto;
    }

    //获取国外的精确匹配的城市
    private AreaDto getForeignCity(List<AreaDto> areaCityDtos, String cityName) {
        AreaDto cityDto = new AreaDto();
        for (AreaDto areaDto : areaCityDtos) {
            if (areaDto.getName().equalsIgnoreCase(cityName)) {
                cityDto = areaDto;
                break;
            }
        }
        return cityDto;
    }

    private String changeCountry(String countryName) {
        String countryNameResult = "";

        if (LanguageCode.CN_UPPER.equals(countryName.toUpperCase())) {
            countryNameResult = LanguageCode.CN_UPPER;
        }
        return countryNameResult;
    }

    private boolean checkPortOrAirPort(OrderAddressModel orderAddressModel, String transportType) {
        Map<String, Object> type2Object = Maps.newHashMap();
        boolean isValidFromPort = this.judgePort(orderAddressModel.getDistrictName(), orderAddressModel.getCountryCode(), transportType, type2Object);
        if (!isValidFromPort) {
            return false;
        } else {
            this.setAddressModelAirPortOrPort(type2Object, transportType, orderAddressModel);
        }
        return true;
    }

    /**
     * 根据类型来查询机场或港口的数据是否存在
     *
     * @param param 如果type为为海运传的是中文名称或英文名称，type为机场，传的是三字码
     * @param type  CommCodes.TRANSPORT_SEA 海运 CommCodes.TRANSPORT_AIR 机场
     * @return true 有效的机场或港口，false 无效的机场或港口
     */
    private boolean judgePort(String param, String countryCode, String type, Map<String, Object> type2Object) {
        boolean bFind = false;
        if (!StringUtils.isEmpty(param) && !StringUtils.isEmpty(type)) {
            if (type.equals(String.valueOf(CommCodes.TRANSPORT_SEA))) {
                List<Port> ports = portService.findPortByName(param, countryCode);
                if (!CollectionUtils.isEmpty(ports) && ports.size() > 0) {
                    type2Object.put(String.valueOf(CommCodes.TRANSPORT_SEA), ports.get(0));
                    bFind = true;
                }
            } else if (type.equals(String.valueOf(CommCodes.TRANSPORT_AIR))) {
                Airport airport = airportService.findAirPortByTriadCode(param, countryCode);
                if (!ObjectUtils.isEmpty(airport)) {
                    type2Object.put(String.valueOf(CommCodes.TRANSPORT_AIR), airport);
                    bFind = true;
                }
            }
        }
        return bFind;
    }

    /**
     * 批量保存或者提交订单， orderstatus 仅有2种值，草稿或者已提交
     *
     * @param batchNumber
     * @param orderStatus
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void saveBatchOrder(String batchNumber, OrderStatus orderStatus) {
        long beginTime = System.currentTimeMillis();
        if (null == orderStatus || (orderStatus != OrderStatus.DRAFT && orderStatus != OrderStatus.COMMITED)) {
            return;
        }
        List<OrdOrderBatch> batchList = this.findByBatchNumber(batchNumber);//获取批次的数据
        if (CollectionUtils.isEmpty(batchList)) {
            throw Exceptions.bizException(ErrorCodes.ERROR_ORD_ORDER_BATCH_EMPTY);
        }
        List<Integer> failedIdList = Lists.newArrayList();
        //再一次校验客户单号的唯一性
        //再一次校验产品信息
        //获取产品nameOrCode与产品的对应关系
        long checkTime = System.currentTimeMillis();
        Map<String, List<Product>> nameOrCode2lstProductMap = getExcelProductInfo(batchList);
        if (!CollectionUtils.isEmpty(batchList)) {
            for (OrdOrderBatch orderBatch :
                    batchList) {
                if (!orderBatch.getVerifiedStatus()) {
                    throw Exceptions.bizException(ErrorCodes.ERROR_ORD_ORDER_BATCH_VERIFIED_FAIL);
                }
                if (!checkExternalNo(orderBatch.getExternalNo(), orderBatch.getCustomerId())) {
                    orderBatch.setVerifiedStatus(false);
                    failedIdList.add(orderBatch.getId());
                }
                Map<String, OrdOrderBatchErrorDto> errorCode2Msg = Maps.newHashMap();
                checkProductInfo(orderBatch, errorCode2Msg, nameOrCode2lstProductMap);
                if (!CollectionUtils.isEmpty(errorCode2Msg)) {
                    //产品校验失败
                    if (!failedIdList.contains(orderBatch.getId())) {
                        failedIdList.add(orderBatch.getId());
                    }
                }
            }
        }
        logger.info("checktime:" + (System.currentTimeMillis() - checkTime));
        if (!CollectionUtils.isEmpty(failedIdList)) {
            //批量更新状态，同时给客户端提示
            updateVerifiedStatus(failedIdList, false);
            throw Exceptions.bizException(ErrorCodes.ERROR_ORD_ORDER_BATCH_VERIFIED_FAIL);
        }
        List<OrdOrder> ordOrderList = Lists.newArrayList();//获取订单数据
        List<String> orderNoList = Lists.newArrayList();
        List<Integer> orderIds = Lists.newArrayList();
        List<String> acceptAutoOrderNos = Lists.newArrayList();
        List<Integer> acceptAutoIds = Lists.newArrayList();
        List<OrdOrderAddress> ordOrderAddressList = Lists.newArrayList();//获取订单的地址信息
        List<OrdOrderAdditional> orderAdditionalList = Lists.newArrayList();//获取订单的可选服务
        List<OrdOrderCargo> orderBatchCargoList = Lists.newArrayList();//获取订单的货物信息
        List<OrdOrderFile> orderFileList = Lists.newArrayList();//获取订单的货物信息
        List<OrdSubOrder> subOrderList = Lists.newArrayList();//获取订单的子单信息
        List<OrdOrderTracking> orderTrackingList = Lists.newArrayList();//获取订单的物流信息
        Map<String, Integer> productMap = Maps.newHashMap();
        long dealOrderTime = System.currentTimeMillis();
        // todo  获取Map参数
        for (OrdOrderBatch ordOrderBatch : batchList) {
            String redundanceData = ordOrderBatch.getRedundanceData();
            Map<String, String> dataMap = getStringStringMap(redundanceData);
            productMap.put(dataMap.get("productUid"), Integer.parseInt(dataMap.get("productGroupLeafId")));
            String orderNo;
            try {
                orderNo = OrderMake.generateOrderNo();
                orderNoList.add(orderNo);
            } catch (Exception e) {
                //订单号生成异常
                throw Exceptions.bizException(ErrorCodes.ERROR_ORD_ORDER_ORDERNO_EXCEPTION);
            }

            //保存订单
            OrdOrder ordOrder = this.getOrdOrder(ordOrderBatch, orderNo);
            ordOrder.setOrderStatus(orderStatus);
            //草稿状态下给运单号设置订单号的值
            if(ordOrder.getOrderStatus()==OrderStatus.DRAFT){
                ordOrder.setWaybillNo(orderNo);
            }
            ordOrderList.add(ordOrder);
            //保存可选服务
            String serviceTypeCodes = ordOrderBatch.getAdditionalTypeCode();
            List<OrdOrderAdditional> additionals = this.getOrdOrderAdditionals(serviceTypeCodes, orderNo);
            orderAdditionalList.addAll(additionals);
            //保存货物明细
            String cargos = ordOrderBatch.getGoodsDetail();
            List<OrdOrderCargo> ordOrderCargos = this.getOrdOrderCargos(cargos, orderNo);
            orderBatchCargoList.addAll(ordOrderCargos);
            //保存地址信息
            OrdOrderAddress ordOrderAddress = this.getOrdOrderAddress(ordOrderBatch, orderNo);
            ordOrderAddressList.add(ordOrderAddress);
            //附件信息
            String attaches = ordOrderBatch.getAttaches();
            List<OrdOrderFile> ordOrderFiles = this.getOrdOrderFiles(attaches, orderNo);
            orderFileList.addAll(ordOrderFiles);
        }

        long startGetWaybillNoTime = System.currentTimeMillis();
        List<SerialNoManagement> serialNoManagementList = Lists.newArrayList();
        //处理运单号
        if (orderStatus == OrderStatus.COMMITED) {
            //需要批量生成运单号
             serialNoManagementList  = getWaybillNos(productMap, ordOrderList, null);
        }

        for(OrdOrder order:ordOrderList){
            String orderNo=order.getOrderNo();
            //子单与物流信息
            List<String> suborderNos = Lists.newArrayList();
            //组装子单
            if (orderStatus == OrderStatus.COMMITED) {
                subOrderList.addAll(this.getSubOrders(suborderNos, orderNo, order, orderStatus));
            }
            //处理自动受理
            if (orderStatus == OrderStatus.COMMITED) {
                int acceptType = productService.getProductAcceptType(order.getProductUid());
                if (acceptType == CommCodes.PRODUCT_ACCETP_TYPE_AUTO) {
                    acceptAutoOrderNos.add(order.getOrderNo());
                    order.setOrderStatus(OrderStatus.ACCEPT);
                    //处理子单物流信息,增加已经受理的物流信息
                    List<OrdOrderTracking> acceptTrackings = this.getOrdOrderTrackings(suborderNos, order, OrderStatus.ACCEPT);
                    orderTrackingList.addAll(acceptTrackings);//添加子单物流
                } else {
                    List<OrdOrderTracking> acceptTrackings = this.getOrdOrderTrackings(suborderNos, order, OrderStatus.COMMITED);
                    orderTrackingList.addAll(acceptTrackings);//添加子单物流
                }
            }
        }

        logger.info("startGetWaybillNoTime====="+(System.currentTimeMillis()-startGetWaybillNoTime));
        logger.info("dealOrderTime:" + (System.currentTimeMillis() - dealOrderTime));
        //设置订单信息中默认值
        long saveTime = System.currentTimeMillis();

        ordOrderService.batchSaveOrder(ordOrderList, serialNoManagementList);

        orderAddressService.batchSave(ordOrderAddressList);
        orderAdditionalService.batchSave(orderAdditionalList);
        orderCargoService.batchSave(orderBatchCargoList);
        subOrderService.batchSave(subOrderList);
        orderTrackingService.batchSave(orderTrackingList);
        //费用预估，分派服务
        if (orderStatus == OrderStatus.COMMITED) {
            for(OrdOrder ordOrder:ordOrderList){
                orderFeeService.submitBillByAccept(ordOrder.getOrderNo());
            }
        }
        orderFileService.batchSaveOrderFiles(orderFileList);
        logger.info("saveTime:" + (System.currentTimeMillis() - saveTime));
        //删掉批量数据
        long deleteTime = System.currentTimeMillis();
        deleteByBatchNumber(batchNumber);
        logger.info("deleteTIme:" + (System.currentTimeMillis() - saveTime));
        //增加订单的操作日志
        ordOrderList.forEach(ordOrder -> {
            orderIds.add(ordOrder.getId());
            if (acceptAutoOrderNos.contains(ordOrder.getOrderNo())) {
                acceptAutoIds.add(ordOrder.getId());
            }
        });

        logger.info("totalTime:" + (System.currentTimeMillis() - beginTime));
        Integer accountId = PrincipalUtils.getAccountId();
        Integer domainId = PrincipalUtils.getDomainId();
        OrdOperationLogEnum operationLogEnum;
        if (orderStatus == OrderStatus.DRAFT) {
            operationLogEnum = OrdOperationLogEnum.CREATE_DRAFT;
        } else {
            operationLogEnum = OrdOperationLogEnum.SUBMIT_ORDER;
        }
        bizOperationLogService.saveOrdOperLogForDraftOrCommit(orderIds, accountId, domainId, operationLogEnum);
        //处理自动受理时，增加一个操作日志
        if (!CollectionUtils.isEmpty(acceptAutoIds)) {
            bizOperationLogService.saveOrdOperLogForBatchAcceptOrSubmit(acceptAutoIds, UserActions.UPDATE, accountId, domainId, OrdOperationLogEnum.ACCEPT_ORDER);
        }

        //增加系统操作日志
        Map<String, Object> dataBackup = new HashMap<>();
        dataBackup.put("ADD_ORD_ORDER_FROM_BATCH", ordOrderList);
        PrincipalLogUtils.addOperationLog(ModuleNames.ORD, ModuleNames.ORD_ORDER, UserActions.ADD, "从excel批量新增订单", dataBackup);

        if (!CollectionUtils.isEmpty(orderNoList)) {
            //启动一个线程去计算服务分配
            submitBill(orderNoList);
        }
    }

    /**
     * 入库之前处理运单号重复
     * @param ordOrderList
     * @param order2MapMap
     * @param serialNoManagementList
     */
    private void dealWithSameWaybillNo(List<OrdOrder> ordOrderList, Map<String, Map<String, Integer>> order2MapMap,List<SerialNoManagement> serialNoManagementList) {
        if(CollectionUtils.isEmpty(ordOrderList)){
             return;
        }
        else {
            //运单号与订单的Map
            Map<String ,List<OrdOrder>> waybillNo2LstOrderMap=Maps.newHashMap();
            for(OrdOrder ordOrder:ordOrderList){
                String waybillNo=ordOrder.getWaybillNo();
                if(null==waybillNo2LstOrderMap.get(waybillNo)){
                    waybillNo2LstOrderMap.put(waybillNo,Lists.newArrayList());
                }
                waybillNo2LstOrderMap.get(waybillNo).add(ordOrder);
            }
            List<OrdOrder> sameNoOrderLst=Lists.newArrayList();
            for(Map.Entry<String ,List<OrdOrder>> entry:waybillNo2LstOrderMap.entrySet()){
                List<OrdOrder> lstOrder=entry.getValue();
                if(!CollectionUtils.isEmpty(lstOrder) && lstOrder.size()>1){
                    sameNoOrderLst.addAll(lstOrder);
                }
            }
            Map<String,Integer> productInfoMap=Maps.newHashMap();
            for(OrdOrder ordOrder:sameNoOrderLst){
                String orderNo=ordOrder.getOrderNo();
                Map<String,Integer> oneMap=order2MapMap.get(orderNo);
                productInfoMap.putAll(oneMap);
            }
            if(CollectionUtils.isEmpty(sameNoOrderLst)){
                return;
            }
            List<Long> oldIds=getSameWaybillNoIds(sameNoOrderLst,serialNoManagementList);
            List<SerialNoManagement> serialNoManagements = getWaybillNos(productInfoMap, sameNoOrderLst, oldIds);
            setNewWaybillno(sameNoOrderLst,ordOrderList);
            dealWithSameWaybillNo(ordOrderList,order2MapMap,serialNoManagements);
        }
    }

    private void setNewWaybillno(List<OrdOrder> sameNoOrderLst,List<OrdOrder> orderLst){
        for(OrdOrder ordOrder:sameNoOrderLst){
            for(OrdOrder order: orderLst){
                if(ordOrder.getOrderNo().equals(order.getOrderNo())){
                    order.setWaybillNo(ordOrder.getWaybillNo());
                }
            }
        }
    }

    private List<Long> getSameWaybillNoIds(List<OrdOrder> lstOrdOrder,List<SerialNoManagement> lstSerialNoManagement){
        List<Long> lstId= Lists.newArrayList();
        for(OrdOrder ordOrder:lstOrdOrder){
            for(SerialNoManagement serialNoManagement:lstSerialNoManagement){
                if(ordOrder.getWaybillNo().equals(serialNoManagement.getSerialNumber())){
                    lstId.add(serialNoManagement.getId());
                }
            }
        }
        return null;
    }

    /**
     * 获取运单号
     */
    private List<SerialNoManagement> getWaybillNos(Map<String, Integer> productMap, List<OrdOrder> ordOrderList, List<Long> oldIds) {
        Map<String, Map<String, OrdOrder>> map = Maps.newHashMap();
        List<OrdOrder> ordOrderListResult = Lists.newArrayList();

        List<SerialNoManagement> serialNoManagementList = Lists.newArrayList();
        if (!CollectionUtils.isEmpty(productMap) && !CollectionUtils.isEmpty(ordOrderList)) {
            ordOrderList.forEach(ordOrder -> {
                String productUid = ordOrder.getProductUid();
                if (!productMap.containsKey(productUid) || null == productMap.get(productUid)) {
                    //运单号处理异常
                    throw Exceptions.bizException(ErrorCodes.ERROR_ORD_ORDER_WAYBILLNO_EXCEPTION);
                }
                String key = "customerId:" + ordOrder.getCustomerId() + "|" + "productUid:" + productUid + "|" + "productGroupLeafId:" + productMap.get(productUid);
                if (map.containsKey(key)) {
                    if (!map.get(key).containsKey(ordOrder.getOrderNo())) {
                        map.get(key).put(ordOrder.getOrderNo(), ordOrder);
                    }
                } else {
                    Map<String, OrdOrder> orderMap = Maps.newHashMap();
                    orderMap.put(ordOrder.getOrderNo(), ordOrder);
                    map.put(key, orderMap);
                }
            });
            if (!CollectionUtils.isEmpty(map)) {
                //去获取运单号
                map.forEach((k, v) -> {
                    Map<String, String> paramMap = getStringStringMap(k);
                    Integer customerId = Integer.parseInt(paramMap.get("customerId"));
                    String productUid = paramMap.get("productUid");
                    String pGroupLeafId = paramMap.get("productGroupLeafId");
                    Integer productGroupLeafId = Integer.parseInt(pGroupLeafId);
                    Map<String, OrdOrder> orderMap = v;
                    List<String> ordNos = Lists.newArrayList();
                    orderMap.forEach((orderNo, ordOrder) -> {
                        ordNos.add(orderNo);
                    });
                    //第一次获取

                    List<SerialNoManagement> waybillNosResult = noManagementService.getWayBillNos(oldIds,productUid, productGroupLeafId, ordNos, customerId);
                    if (CollectionUtils.isEmpty(waybillNosResult) || waybillNosResult.size() != ordNos.size()) {
                        // 运单号不够
                        throw Exceptions.bizException(ErrorCodes.ERROR_ORD_ORDER_WAYBILLNO_LESS_EXCEPTION);
                    }
                    serialNoManagementList.addAll(waybillNosResult);
                    Map<String, SerialNoManagement> waybillNosMap = Maps.newHashMap();

                    waybillNosResult.forEach(channelNoManagement -> {
                        waybillNosMap.put(channelNoManagement.getOrderNumber(), channelNoManagement);
                    });
                    orderMap.forEach(((orderNo, ordOrder) -> {
                        ordOrder.setWaybillNo(waybillNosMap.get(orderNo).getSerialNumber());
                        ordOrderListResult.add(ordOrder);
                    }));

                });
                ordOrderList  = ordOrderListResult;
            }

        }

        return serialNoManagementList;
    }

    private List<OrdOrderFile> getOrdOrderFiles(String attaches, String orderNo) {
        List<OrdOrderFile> ordOrderFiles = new ArrayList<>();
        if (!StringUtils.isEmpty(attaches)) {
            OrdOrderBatchFileList orderBatchFileList = JsonUtils.toObject(attaches, OrdOrderBatchFileList.class);
            for (OrdOrderFileDto orderFileDto : orderBatchFileList.getAttaches()) {
                OrdOrderFile ordOrderFile = new OrdOrderFile();
                EntityUtils.copyPropertiesIgnoreNull(orderFileDto, ordOrderFile);
                ordOrderFile.setId(null);
                ordOrderFile.setCreateUserType(CommCodes.CUSTOMER_USER_TYPE);
                ordOrderFile.setOrderNo(orderNo);
                ordOrderFile.setFileId(orderFileDto.getFileId());
                ordOrderFile.setLastUpdateTime(ordOrderFile.getCreateTime());
                ordOrderFiles.add(ordOrderFile);
            }
        }
        return ordOrderFiles;
    }

    /**
     * 组装子单
     *
     * @param orderNo
     * @param ordOrder
     * @param orderStatus
     * @return
     */
    private List<OrdSubOrder> getSubOrders(List<String> suborderNos, String orderNo, OrdOrder ordOrder, OrderStatus orderStatus) {
        List<OrdSubOrder> subOrderList = Lists.newArrayList();
        List<OrdSubOrder> subOrders = Lists.newArrayList();
        List<String> subOrderNos = subOrderService.generateSubOrderNo(ordOrder.getWaybillNo(), ordOrder.getPackageNum());
        if (CollectionUtils.isEmpty(subOrderNos)) {
            return subOrderList;
        }
        for (int i = 0; i < ordOrder.getPackageNum(); i++) {
            OrdSubOrder subOrder = new OrdSubOrder();
            subOrder.setOrderNo(orderNo);
            subOrder.setSubOrderNo(subOrderNos.get(i));
            subOrder.setOrderStatus(orderStatus);
            subOrders.add(subOrder);
            suborderNos.add(subOrder.getSubOrderNo());
        }
        subOrderList.addAll(subOrders);//添加子单
        return subOrderList;
    }

    /**
     * 得到物流信息
     *
     * @param suborderNos
     * @param ordOrder
     * @param orderStatus
     * @return
     */
    private List<OrdOrderTracking> getOrdOrderTrackings(List<String> suborderNos, OrdOrder ordOrder, OrderStatus orderStatus) {

        return subOrderService.batchAddSubTrackings(ordOrder.getOrderNo(), ordOrder.getWaybillNo(), orderStatus, suborderNos);
    }

    private OrdOrderAddress getOrdOrderAddress(OrdOrderBatch ordOrderBatch, String orderNo) {
        OrdOrderAddress ordOrderAddress = new OrdOrderAddress();
        EntityUtils.copyPropertiesIgnoreNull(ordOrderBatch, ordOrderAddress);
        ordOrderAddress.setId(null);
        ordOrderAddress.setOrderNo(orderNo);
        //  地址冗余:0-地址类型|1-国家code|2-省份id|3-城市id|4-城区id|5-街道id|6-机场id，或者港口id
        String detailCode = ordOrderBatch.getFromDetailCode();
        Map<String, String> detailCodeMap = this.getStringStringMap(detailCode);
//cusTransportType:11|countryCode:CN|provinceId:610000|cityId:610100|districtId:610113|streetId:610113002|transportId:0
        ordOrderAddress.setFromTransportType(Integer.parseInt(detailCodeMap.get("cusTransportType")));
        ordOrderAddress.setFromCountry(detailCodeMap.get("countryCode"));
        ordOrderAddress.setFromProvince(detailCodeMap.get("provinceId"));
        ordOrderAddress.setFromCity(detailCodeMap.get("cityId"));
        ordOrderAddress.setFromDistrict(detailCodeMap.get("districtId"));
        ordOrderAddress.setFromStreet(detailCodeMap.get("streetId"));
        if (org.apache.commons.lang3.StringUtils.isNotBlank(detailCodeMap.get("transportId"))) {
            ordOrderAddress.setFromTransportId(Integer.parseInt(detailCodeMap.get("transportId")));
        }
        detailCode = ordOrderBatch.getToDetailCode();
        detailCodeMap = this.getStringStringMap(detailCode);
        ordOrderAddress.setToTransportType(Integer.parseInt(detailCodeMap.get("cusTransportType")));
        ordOrderAddress.setToCountry(detailCodeMap.get("countryCode"));
        ordOrderAddress.setToProvince(detailCodeMap.get("provinceId"));
        ordOrderAddress.setToCity(detailCodeMap.get("cityId"));
        ordOrderAddress.setToDistrict(detailCodeMap.get("districtId"));
        ordOrderAddress.setToStreet(detailCodeMap.get("streetId"));
        if (org.apache.commons.lang3.StringUtils.isNotBlank(detailCodeMap.get("transportId"))) {
            ordOrderAddress.setToTransportId(Integer.parseInt(detailCodeMap.get("transportId")));
        }
        detailCode = ordOrderBatch.getFetchDetailCode();
        if (org.apache.commons.lang3.StringUtils.isNotBlank(detailCode)) {
            detailCodeMap = this.getStringStringMap(detailCode);
            ordOrderAddress.setFetchTransportType(Integer.parseInt(detailCodeMap.get("cusTransportType")));
            ordOrderAddress.setFetchCountry(detailCodeMap.get("countryCode"));
            ordOrderAddress.setFetchProvince(detailCodeMap.get("provinceId"));
            ordOrderAddress.setFetchCity(detailCodeMap.get("cityId"));
            ordOrderAddress.setFetchDistrict(detailCodeMap.get("districtId"));
            ordOrderAddress.setFetchStreet(detailCodeMap.get("streetId"));
        }
        ordOrderAddress.setCreateUserId(PrincipalUtils.getAccountId());
        return ordOrderAddress;
    }

    private List<OrdOrderCargo> getOrdOrderCargos(String cargos, String orderNo) {
        List<OrdOrderCargo> ordOrderCargos = new ArrayList<>();
        if (!StringUtils.isEmpty(cargos)) {
            OrdOrderBatchCargoList ordOrderBatchCargoList = JsonUtils.toObject(cargos, OrdOrderBatchCargoList.class);
            for (OrdOrderBatchCargo ordOrderBatchCargo : ordOrderBatchCargoList.getCargos()) {
                OrdOrderCargo ordOrderCargo = new OrdOrderCargo();
                ordOrderCargo.setOrderNo(orderNo);
                EntityUtils.copyPropertiesIgnoreNull(ordOrderBatchCargo, ordOrderCargo);
                ordOrderCargo.setGoodsNumber(Integer.parseInt(ordOrderBatchCargo.getGoodsNumber()));
                ordOrderCargo.setGoodsPrice(new BigDecimal(ordOrderBatchCargo.getGoodsPrice()));
                ordOrderCargos.add(ordOrderCargo);
            }
        }
        return ordOrderCargos;
    }

    private List<OrdOrderAdditional> getOrdOrderAdditionals(String serviceTypeCodes, String orderNo) {
        List<OrdOrderAdditional> additionals = new ArrayList<>();
        if (!StringUtils.isEmpty(serviceTypeCodes)) {
            String[] serviceTypeCode = serviceTypeCodes.split("\\|");
            for (String serviceType : serviceTypeCode) {
                OrdOrderAdditional ordOrderAdditional = new OrdOrderAdditional();
                ordOrderAdditional.setOrderNo(orderNo);
                ordOrderAdditional.setServiceTypeCode(serviceType);
                additionals.add(ordOrderAdditional);
            }
        }

        return additionals;
    }

    private OrdOrder getOrdOrder(OrdOrderBatch ordOrderBatch, String orderNo) {
        OrdOrder ordOrder = new OrdOrder();
        ordOrder.setOrderNo(orderNo);
        ordOrder.setPayStatus(PayStatus.UNPAID);
        ordOrder.setCustomerId(ordOrderBatch.getCustomerId());
        ordOrder.setCusUserId(ordOrderBatch.getCusUserId());
        ordOrder.setCusWeight(new BigDecimal(ordOrderBatch.getCusWeight()));
        ordOrder.setCusWeightUnit(ordOrderBatch.getCusWeightUnit());

        //订单的结算方式，跟客户的结算方式一致:现结，月结等
        CusCustomer customer = customerService.findCustomerById(ordOrder.getCustomerId());
        if (!ObjectUtils.isEmpty(customer)) {
            ordOrder.setSettlementTypeId(customer.getRefSettlementId());
        }
        ordOrder.setType(ordOrderBatch.getType());
        //产品信息
        String redundanceData = ordOrderBatch.getRedundanceData();
        Map<String, String> dataMap = this.getStringStringMap(redundanceData);
        ordOrder.setProductUid(dataMap.get("productUid"));
        //货物类型处理
        ordOrder.setCargoType(dataMap.get("cargoType"));
        ordOrder.setCreateUserId(PrincipalUtils.getAccountId());
        ordOrder.setLastUpdateUserId(PrincipalUtils.getAccountId());

        ordOrder.setCustomerNote(ordOrderBatch.getCustomerNote());
        ordOrder.setExternalNo(ordOrderBatch.getExternalNo());
        ordOrder.setPackageNum(Integer.parseInt(ordOrderBatch.getPackageNum()));
        ordOrder.setTransportStatus(OrderConstants.OrderTransportStatus.ORDER_NO_TRANSPORT);
        ordOrder.setIsDeleted(Boolean.FALSE);
        ordOrder.setValidFlag(Boolean.TRUE);
        return ordOrder;
    }

    private Map<String, String> getStringStringMap(String redundanceData) {
        Map<String, String> dataMap = new HashMap<>();
        if (!StringUtils.isEmpty(redundanceData)) {
            String[] redundance = redundanceData.split("\\|");
            for (String s : redundance) {
                String[] data = s.split(":");
                dataMap.put(data[0], data[1]);
            }
        }
        return dataMap;
    }


    /**
     * 提交计算的运单号
     *
     * @param orderNos 运单号
     */

    public void submitBill(List<String> orderNos) {
        OrdOrderBatchServiceImpl.OrderAssignServiceRunnable command = new OrdOrderBatchServiceImpl.OrderAssignServiceRunnable(orderNos);
        pool.execute(command);
    }


    private class OrderAssignServiceRunnable implements Runnable {
        private List<String> orderNos;

        OrderAssignServiceRunnable(List<String> orderNos) {
            this.orderNos = orderNos;
        }

        @Override
        public void run() {
            try {
                Thread.sleep(10 * 1000);
            } catch (InterruptedException e) {
            }
            for (String orderNo : orderNos) {
                OrdOrder ordOrder = ordOrderService.findByOrderNo(orderNo);
                ProductServiceRel productServiceRel = trackingMessageService
                        .findCurServiceByTracking(ordOrder.getWaybillNo(), ordOrder.getProductUid(), ordOrder.getCreateTime());
                String serviceTypeCode = "";
                if (!ObjectUtils.isEmpty(productServiceRel)) {
                    serviceTypeCode = productServiceRel.getServiceTypeCode();
                }
                ordOrderServiceAssignService.calc(orderNo, serviceTypeCode);
                OrdServiceAssign assign = ordOrderServiceAssignService.findOkAssignByOrderNo(orderNo);
                if (assign != null && assign.getIsAssignOk()) {
                    Object[] object = quotationCalcService.calcFeeByOrderNo(orderNo);
                    //更新订单预估费用信息
                    orderFeeService.saveOrUpdate(orderNo, new BigDecimal((String) object[0]), (String) object[1]);
                }

            }
        }
    }


}
